提交 1fa947a8 作者: 方治民

feat: 实现地图组件的相关常用方法

上级 80e4188f
import type mapboxgl from 'mapbox-gl'
import type { MapboxConfig, MapboxInstance } from './index'
import { isProdMode } from '@/utils/env'
......@@ -41,6 +42,41 @@ export function useMapbox<T extends MapboxInstance, P extends MapboxConfig>(
{
setConfig: (config: Partial<P>) => getInstance()?.setConfig(config),
isReady: computed(() => instanceRef?.value?.isReady) as unknown as ComputedRef<boolean>,
on: (type: string, layerId: string, listener: (...args: any[]) => void) =>
getInstance()?.on(type, layerId, listener),
addSource: (id: string, source: mapboxgl.AnySourceData) => getInstance()?.addSource(id, source),
removeSource: (id: string) => getInstance()?.removeSource(id),
setGeoJSONSourceForRequest: (
id: string,
url: string,
map: (
data: Recordable,
) => GeoJSON.Feature<GeoJSON.Geometry> | GeoJSON.FeatureCollection<GeoJSON.Geometry>,
) => getInstance()?.setGeoJSONSourceForRequest(id, url, map),
setGeoJSONSourceData: (id: string, data: mapboxgl.GeoJSONSource['setData'], filter?: string) =>
getInstance()?.setGeoJSONSourceData(id, data, filter),
setVectorTileSourceTiles: (id: string, tiles: string[]) =>
getInstance()?.setVectorTileSourceTiles(id, tiles),
addLayer: (layer: mapboxgl.Layer) => getInstance()?.addLayer(layer),
removeLayer: (id: string) => getInstance()?.removeLayer(id),
setPaintProperty: (layerId: string, name: string, value: any) =>
getInstance()?.setPaintProperty(layerId, name, value),
setLayoutProperty: (layerId: string, name: string, value: any) =>
getInstance()?.setLayoutProperty(layerId, name, value),
setFilter: (layerId: string, filter: any[]) => getInstance()?.setFilter(layerId, filter),
flyTo: (options: mapboxgl.FlyToOptions) => getInstance()?.flyTo(options),
},
]
}
export function buildGeoJSONSourceDataUrl(config: { url: string; params: Recordable }): string {
const { url, params } = config
const keys = Object.keys(params)
if (keys.length === 0) {
return url
}
const query = keys.map((key) => `${key}=${params[key]}`).join('&')
return `${url}?${query}`
}
import axios from 'axios'
import { merge } from 'lodash-es'
import { defaultStyle, loadMapControl, loadMapboxLibs } from '/@/components/Map/Mapbox'
import { HandlerUtil, defaultStyle, loadMapControl, loadMapboxLibs } from '/@/components/Map/Mapbox'
// renderjs 官方文档
// https://uniapp.dcloud.io/tutorial/renderjs.html
// renderjs 的一些细节问题
// https://juejin.cn/post/7049185827582115870
async function request(url, handler) {
const res = await axios.get(url)
if (handler) {
// TODO: 待优化
// 1. 考虑是否为函数
// 2. 考虑箭头函数的情况,可能意外的兼容性问题
// HandlerUtil 为 renderjs 提供的工具类,用于处理一些常用的数据转换,需要保证逻辑层同样使用此工具类进行处理
console.debug('handler', handler, HandlerUtil)
// eslint-disable-next-line no-eval
const executableFunction = eval(`(${handler})`)
return executableFunction(res.data)
}
return res.data
}
const defaultEmptyGeoJSON = {
type: 'FeatureCollection',
features: [],
}
export default {
mounted() {},
methods: {
......@@ -102,12 +127,19 @@ export default {
// TODO: 加载地图图层
return Promise.resolve()
},
// 检测触发变更时候的有效性
checkOnChangeValidity(options) {
return options && Object.keys(options).length > 0 && this.map
},
emitChangeEvent(type) {
// 通知逻辑层,本次变更事件已经送达
this.$ownerInstance.callMethod('onMapOptionsChangeEvent', { type })
},
changeOptions(options) {
if (!options.container) {
return
}
console.log(options)
if (typeof window.mapboxgl === 'object') {
this.initMap(options)
} else {
......@@ -116,5 +148,110 @@ export default {
})
}
},
changeFlyToOptions(options) {
this.emitChangeEvent('flyTo')
if (this.checkOnChangeValidity(options)) {
this.map.flyTo(options)
}
},
changeAddSourceOptions(options) {
this.emitChangeEvent('addSource')
if (this.checkOnChangeValidity(options)) {
this.map.addSource(options.id, options.source)
}
},
changeSetGeoJSONSourceForRequestOptions(options) {
this.emitChangeEvent('setGeoJSONSourceForRequest')
if (this.checkOnChangeValidity(options)) {
if (this.map.getSource(options.id)) {
// 清空数据
this.map.getSource(options.id).setData(defaultEmptyGeoJSON)
} else {
// 添加空的 source
this.map.addSource(options.id, {
type: 'geojson',
data: defaultEmptyGeoJSON,
})
}
// 请求数据
request(options.url, options.handler).then((data) => {
this.map.getSource(options.id).setData(data)
})
}
},
changeSetGeoJSONSourceDataOptions(options) {
this.emitChangeEvent('setGeoJSONSourceData')
if (this.checkOnChangeValidity(options)) {
this.map.getSource(options.id).setData(options.data)
}
},
changeSetVectorTileSourceTilesOptions(options) {
this.emitChangeEvent('setVectorTileSourceTiles')
if (this.checkOnChangeValidity(options)) {
this.map.getSource(options.id).setTiles(options.tiles)
}
},
changeAddLayerOptions(options) {
this.emitChangeEvent('addLayer')
if (this.checkOnChangeValidity(options)) {
this.map.addLayer(options.layer, options.beforeId)
}
},
changeRemoveOptions(options) {
this.emitChangeEvent('remove')
if (this.checkOnChangeValidity(options)) {
if (options.type === 'layer') {
this.map.removeLayer(options.id)
} else if (options.type === 'source') {
this.map.removeSource(options.id)
}
}
},
changeSetFilterOptions(options) {
this.emitChangeEvent('filter')
if (this.checkOnChangeValidity(options)) {
this.map.setFilter(options.layer, options.filter)
}
},
changeSetLayoutPropertyOptions(options) {
this.emitChangeEvent('setLayoutProperty')
if (this.checkOnChangeValidity(options)) {
this.map.setLayoutProperty(options.layer, options.name, options.value)
}
},
changeSetPaintPropertyOptions(options) {
this.emitChangeEvent('setPaintProperty')
if (this.checkOnChangeValidity(options)) {
this.map.setPaintProperty(options.layer, options.name, options.value)
}
},
changeEventOptions(options) {
this.emitChangeEvent('event')
if (this.checkOnChangeValidity(options)) {
if (options.event === 'on') {
if (options.type === 'click') {
this.map.on(options.type, options.layer, (e) => {
console.log('e', e)
const feature = e.features[0]
new window.mapboxgl.Popup()
.setLngLat(feature.geometry.coordinates)
.setHTML(
feature.properties.popup
.replace('{key}', feature.properties.key)
.replace('{value}', feature.properties.value)
.replace('{suffix}', feature.properties.suffix || ''),
)
.addTo(this.map)
this.$ownerInstance.callMethod('onEvent', options)
})
} else {
this.map.on(options.type, options.layer, () => {})
}
} else if (options.event === 'off') {
this.map.off(options.type, options.layer, () => {})
}
}
},
},
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论