提交 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}`
}
......@@ -78,63 +78,63 @@ export const defaultStyle: mapboxgl.Style = {
url: `${host}/api/tilesets/430000.area.label/tilejson`,
},
// ============ 流域河流数据源 ============
/** 湖南省-全流域及遮罩 */
'430000.watershed-quan-liu-yu': {
type: 'vector',
url: `${host}/api/tilesets/watershed-quan-liu-yu/tilejson`,
minzoom: 0,
maxzoom: 11,
bounds: [87.638275, 8.296956, 136.638275, 44.385598],
},
/** 湖南省-大河流域 */
'430000.watershed-big': {
type: 'vector',
url: `${host}/api/tilesets/watershed-big/tilejson`,
minzoom: 1,
maxzoom: 13,
bounds: [107.264454, 23.925618, 114.296651, 30.548506],
},
/** 湖南省-大河流域名称 */
'430000.watershed-big-label': {
type: 'vector',
url: `${host}/api/tilesets/watershed-big-label/tilejson`,
minzoom: 0,
maxzoom: 0,
bounds: [109.539, 26.6586, 112.632, 29.6013],
},
/** 湖南省-中小河流域 */
'430000.watershed-medium': {
type: 'vector',
url: `${host}/api/tilesets/watershed-medium/tilejson`,
minzoom: 0,
maxzoom: 11,
bounds: [107.264454, 23.925618, 114.296644, 30.548506],
},
/** 湖南省-中小河流域名称 */
'430000.watershed-medium-label': {
type: 'vector',
url: `${host}/api/tilesets/watershed-medium-label/tilejson`,
minzoom: 0,
maxzoom: 0,
bounds: [108.3062, 24.5421, 114.074, 30.0494],
},
/** 湖南省-上中下游边界 */
'430000.watershed-big-medium': {
type: 'vector',
url: `${host}/api/tilesets/watershed-big-medium/tilejson`,
minzoom: 0,
maxzoom: 12,
bounds: [107.264454, 23.925618, 114.296651, 30.548506],
},
/** 湖南省-二级河流 */
'430000.river-secondary': {
type: 'vector',
url: `${host}/api/tilesets/river-secondary/tilejson`,
minzoom: 0,
maxzoom: 9,
bounds: [87.638275, 8.296956, 136.638275, 44.385598],
},
// // ============ 流域河流数据源 ============
// /** 湖南省-全流域及遮罩 */
// '430000.watershed-quan-liu-yu': {
// type: 'vector',
// url: `${host}/api/tilesets/watershed-quan-liu-yu/tilejson`,
// minzoom: 0,
// maxzoom: 11,
// bounds: [87.638275, 8.296956, 136.638275, 44.385598],
// },
// /** 湖南省-大河流域 */
// '430000.watershed-big': {
// type: 'vector',
// url: `${host}/api/tilesets/watershed-big/tilejson`,
// minzoom: 1,
// maxzoom: 13,
// bounds: [107.264454, 23.925618, 114.296651, 30.548506],
// },
// /** 湖南省-大河流域名称 */
// '430000.watershed-big-label': {
// type: 'vector',
// url: `${host}/api/tilesets/watershed-big-label/tilejson`,
// minzoom: 0,
// maxzoom: 0,
// bounds: [109.539, 26.6586, 112.632, 29.6013],
// },
// /** 湖南省-中小河流域 */
// '430000.watershed-medium': {
// type: 'vector',
// url: `${host}/api/tilesets/watershed-medium/tilejson`,
// minzoom: 0,
// maxzoom: 11,
// bounds: [107.264454, 23.925618, 114.296644, 30.548506],
// },
// /** 湖南省-中小河流域名称 */
// '430000.watershed-medium-label': {
// type: 'vector',
// url: `${host}/api/tilesets/watershed-medium-label/tilejson`,
// minzoom: 0,
// maxzoom: 0,
// bounds: [108.3062, 24.5421, 114.074, 30.0494],
// },
// /** 湖南省-上中下游边界 */
// '430000.watershed-big-medium': {
// type: 'vector',
// url: `${host}/api/tilesets/watershed-big-medium/tilejson`,
// minzoom: 0,
// maxzoom: 12,
// bounds: [107.264454, 23.925618, 114.296651, 30.548506],
// },
// /** 湖南省-二级河流 */
// '430000.river-secondary': {
// type: 'vector',
// url: `${host}/api/tilesets/river-secondary/tilejson`,
// minzoom: 0,
// maxzoom: 9,
// bounds: [87.638275, 8.296956, 136.638275, 44.385598],
// },
},
layers: [
// 默认图层 - 影像底图
......@@ -178,6 +178,12 @@ export const defaultStyle: mapboxgl.Style = {
'sky-opacity': ['interpolate', ['exponential', 0.1], ['zoom'], 5, 0, 22, 1],
},
},
// 色斑渲染占位图层
{
id: 'fill-placeholder',
type: 'background',
layout: { visibility: 'none' },
},
// ============ 全国边界图层 ============
// 自定义图层
......@@ -315,6 +321,13 @@ export const defaultStyle: mapboxgl.Style = {
},
minzoom: 8,
},
// 数值渲染占位图层
{
id: 'symbol-placeholder',
type: 'background',
layout: { visibility: 'none' },
},
],
}
......@@ -833,4 +846,150 @@ export interface MapboxInstance {
* 地图组件是否准备好了
*/
isReady: ComputedRef<boolean>
/**
* 监听地图事件
* @param type 事件类型
* @param layerId 图层 ID
* @param listener 事件监听器
* @link https://docs.mapbox.com/mapbox-gl-js/api/map/#map#on
*/
on: (type: string, layerId: string, listener: (...args: any[]) => void) => void
/**
* 飞行到指定位置
* @param options 飞行参数
* @link https://docs.mapbox.com/mapbox-gl-js/api/map/#map#flyto
*/
flyTo: (options: mapboxgl.FlyToOptions) => void
/**
* 添加数据源
* @param id 数据源 ID
* @param source 数据源
* @link https://docs.mapbox.com/mapbox-gl-js/api/map/#map#addsource
*/
addSource: (id: string, source: mapboxgl.AnySourceData) => void
/**
* 移除数据源
* @param id 数据源 ID
* @link https://docs.mapbox.com/mapbox-gl-js/api/map/#map#removesource
*/
removeSource: (id: string) => void
/**
* 设置 GeoJSON 数据源,如果数据源不存在则创建
* @param id 数据源 ID
* @param url 数据源 URL,通常是一个后端的数据查询接口(色斑图查询接口、站点数据查询接口)
* @param map 数据映射函数,用于处理后端返回的数据,将其转换为 GeoJSON 数据
* @link https://docs.mapbox.com/mapbox-gl-js/api/map/#map#addsource
*/
setGeoJSONSourceForRequest: (
id: string,
url: string,
map: (
data: Recordable,
) => GeoJSON.Feature<GeoJSON.Geometry> | GeoJSON.FeatureCollection<GeoJSON.Geometry> | any,
) => void
/**
* 设置 GeoJSONSource 数据源 data
* @param id 数据源 ID
* @param data 数据
* @param filter 过滤器, 可选, 过滤 JSON 数据, 使用 json path 语法
* @link https://docs.mapbox.com/mapbox-gl-js/api/sources/#geojsonsource#setdata
*/
setGeoJSONSourceData: (id: string, data: mapboxgl.GeoJSONSource['setData'], filter?: string) => void
/**
* 设置 VectorTileSource 数据源 tiles
* @param id 数据源 ID
* @param tiles 瓦片源
* @link https://docs.mapbox.com/mapbox-gl-js/api/sources/#vectortilesource#settiles
*/
setVectorTileSourceTiles: (id: string, tiles: string[]) => void
/**
* 添加图层
* @param layer 图层
* @param before 在指定图层之前插入
* @link https://docs.mapbox.com/mapbox-gl-js/api/map/#map#addlayer
*/
addLayer: (layer: mapboxgl.Layer, before?: string) => void
/**
* 移除图层
* @param id 图层 ID
* @link https://docs.mapbox.com/mapbox-gl-js/api/map/#map#removelayer
*/
removeLayer: (id: string) => void
/**
* 设置图层过滤器
* @param layerId 图层 ID
* @param filter 过滤器
* @link https://docs.mapbox.com/mapbox-gl-js/api/map/#map#setfilter
*/
setFilter: (layerId: string, filter: any[]) => void
/**
* 设置图层样式
* @param layerId 图层 ID
* @param name 样式名称
* @param value 样式值
* @link https://docs.mapbox.com/mapbox-gl-js/api/map/#map#setpaintproperty
*/
setPaintProperty: (layerId: string, name: string, value: any) => void
/**
* 设置图层样式
* @param layerId 图层 ID
* @param name 样式名称
* @param value 样式值
* @link https://docs.mapbox.com/mapbox-gl-js/api/map/#map#setlayoutproperty
*/
setLayoutProperty: (layerId: string, name: string, value: any) => void
}
function isPlainObject(obj: any) {
if (typeof obj !== 'object' || obj === null) {
return false
}
const proto = Object.getPrototypeOf(obj)
return proto === null || proto === Object.prototype
}
export const HandlerUtil = {
isPlainObject,
createDefaultGeoJSONFeatureData(station: Recordable) {
return {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [Number(station.lon), Number(station.lat)],
},
properties: {
key: station.key,
suffix: station.suffix,
value: Number(station.value),
popup: HandlerUtil.createDefaultStylePopupHtml({ '{key}': '{value}{suffix}' }, station),
},
}
},
createDefaultGeoJSONSymbolSourceData(features: GeoJSON.Feature<GeoJSON.Geometry>[] = []) {
return {
type: 'FeatureCollection',
features: features || [],
}
},
createDefaultStylePopupHtml(map: Recordable, station: Recordable) {
const htmls = ['<div class="custom-popup">']
if (isPlainObject(station)) {
htmls.push(`<div class="popup-row"><span class="popup-title">站号:</span>${station.stationCode}</div>`)
htmls.push(
`<div class="popup-row"><span class="popup-title">站名:</span>${station.city} ${station.cnty} ${station.stationName}</div>`,
)
}
if (isPlainObject(map)) {
for (const key in map) {
htmls.push(`<div class="popup-row"><span class="popup-title">${key}:</span>${map[key]}</div>`)
}
}
htmls.push('</div>')
return htmls.join('')
},
}
......@@ -11,17 +11,45 @@
// 1. 通过在逻辑层 data 中设置的属性向视图层传递数据
// 2. 通过在逻辑层 methods 定义方法,在视图层调用传递参数(注意:只能传递可进行 JSON 序列化的数据)
function nail() {}
function noop() {}
export default {
emits: ['register'],
data() {
return {
id: nanoid(),
onLoaded: nail,
onLoaded: noop,
options: {},
// FIXED: 定义为 undefined,避免在 Hook 中通过计算属性取值是出现两次变化的问题
loaded: undefined,
// 以下是一些 mapbox 的方法所需参数,方便传递到 renderjs 中
events: {},
eventOptions: undefined,
eventOptionsQueue: [],
addSourceOptions: undefined,
addSourceOptionsQueue: [],
addLayerOptions: undefined,
addLayerOptionsQueue: [],
removeOptions: undefined,
removeOptionsQueue: [],
setGeoJSONSourceForRequestOptions: undefined,
setGeoJSONSourceForRequestOptionsQueue: [],
setGeoJSONSourceDataOptions: undefined,
setGeoJSONSourceDataOptionsQueue: [],
setVectorTileSourceTilesOptions: undefined,
setVectorTileSourceTilesOptionsQueue: [],
setFilterOptions: undefined,
setFilterOptionsQueue: [],
setPaintPropertyOptions: undefined,
setPaintPropertyOptionsQueue: [],
setLayoutPropertyOptions: undefined,
setLayoutPropertyOptionsQueue: [],
flyToOptions: undefined,
flyToOptionsQueue: [],
// change options 锁,结合 event,配合数组实现先进先出队列控制
changeLock: {},
}
},
computed: {
......@@ -44,6 +72,20 @@
// 触发 onLoaded 事件
this.onLoaded?.(this, data)
},
// 尝试触发事件, 通过 changeLock 控制
tryChange(event) {
if (this[`${event.type}OptionsQueue`]?.length && !this.changeLock[event.type]) {
this.changeLock[event.type] = true
this[`${event.type}Options`] = this[`${event.type}OptionsQueue`].shift()
}
},
// 监听地图配置从逻辑层到视图层的响应式变化事件
onMapOptionsChangeEvent(event) {
console.log('✨ Map Event', event)
this.changeLock[event.type] = false
this.tryChange(event)
},
setConfig(config) {
this.options = {
container: this.id,
......@@ -52,7 +94,168 @@
attribution: config?.attribution,
}
this.onLoaded = config?.onLoaded || nail
this.onLoaded = config?.onLoaded || noop
},
// 重新实现 mapbox 的一些方法,方便传递到 renderjs 中
customEvent(event, type, layer, ...args) {
// 加入到 event 事件队列中
this.eventOptionsQueue.push({
event,
type,
layer,
...args,
})
// 尝试触发 event 事件
this.tryChange({ type: 'event' })
return `${event}-${type}-${layer}`
},
// 1. on/once/off 事件监听处理
on(type, layer, listener, popupTemplate) {
const key = this.customEvent('on', type, layer, popupTemplate)
this.events[key] = listener
},
onEvent(event) {
const key = `on-${event.type}-${event.layer}`
this.events[key]?.(event)
},
once(type, layer, listener) {
const key = this.customEvent('once', type, layer)
this.events[key] = listener
},
onceEvent(event) {
const key = `once-${event.type}-${event.layer}`
this.events[key]?.(event)
delete this.events[key]
},
off(type, layer) {
const key = this.customEvent('off', type, layer)
delete this.events[key]
},
// 2. addSource/removeSource 方法
addSource(id, source) {
// 加入到 change 事件队列中
this.addSourceOptionsQueue.push({
id,
source,
})
// 尝试触发 change 事件
this.tryChange({ type: 'addSource' })
},
removeSource(id) {
// 加入到 change 事件队列中
this.removeOptionsQueue.push({
id,
type: 'source',
})
// 尝试触发 change 事件
this.tryChange({ type: 'remove' })
},
setGeoJSONSourceForRequest(id, url, handler) {
// 加入到 change 事件队列中
this.setGeoJSONSourceForRequestOptionsQueue.push({
id,
url,
handler: handler.toString(),
})
// 尝试触发 change 事件
this.tryChange({ type: 'setGeoJSONSourceForRequest' })
},
setGeoJSONSourceData(id, data, filter) {
// 加入到 change 事件队列中
this.setGeoJSONSourceDataOptionsQueue.push({
id,
data,
filter,
})
// 尝试触发 change 事件
this.tryChange({ type: 'setGeoJSONSourceData' })
},
setVectorTileSourceTiles(id, tiles) {
// 加入到 change 事件队列中
this.setVectorTileSourceTilesOptionsQueue.push({
id,
tiles,
})
// 尝试触发 change 事件
this.tryChange({ type: 'setVectorTileSourceTiles' })
},
// 3. addLayer/removeLayer 方法
addLayer(layer, beforeId) {
// 加入到 change 事件队列中
this.addLayerOptionsQueue.push({
layer,
beforeId,
})
// 尝试触发 change 事件
this.tryChange({ type: 'addLayer' })
},
removeLayer(id) {
// 加入到 change 事件队列中
this.removeOptionsQueue.push({
id,
type: 'layer',
})
// 尝试触发 change 事件
this.tryChange({ type: 'remove' })
},
// 4. setFilter 方法
setFilter(layerId, filter) {
// 加入到 change 事件队列中
this.setFilterOptionsQueue.push({
layerId,
filter,
})
// 尝试触发 change 事件
this.tryChange({ type: 'setFilter' })
},
// 5. setPaintProperty 方法
setPaintProperty(layerId, paintProperty, value) {
// 加入到 change 事件队列中
this.setPaintPropertyOptionsQueue.push({
layerId,
paintProperty,
value,
})
// 尝试触发 change 事件
this.tryChange({ type: 'setPaintProperty' })
},
// 6. setLayoutProperty 方法
setLayoutProperty(layerId, layoutProperty, value) {
// 加入到 change 事件队列中
this.setLayoutPropertyOptionsQueue.push({
layerId,
layoutProperty,
value,
})
// 尝试触发 change 事件
this.tryChange({ type: 'setLayoutProperty' })
},
// 7. flyTo 方法
flyTo(options) {
// 加入到 change 事件队列中
this.flyToOptionsQueue.push(options)
// 尝试触发 change 事件
this.tryChange({ type: 'flyTo' })
},
},
}
......@@ -63,7 +266,34 @@
<template>
<!-- #ifdef APP-PLUS || H5 -->
<view class="map wrap" :id="id" :options="options" :change:options="mapbox.changeOptions" />
<view
class="map wrap"
:id="id"
:options="options"
:change:options="mapbox.changeOptions"
:eventOptions="eventOptions"
:change:eventOptions="mapbox.changeEventOptions"
:addSourceOptions="addSourceOptions"
:change:addSourceOptions="mapbox.changeAddSourceOptions"
:setGeoJSONSourceForRequestOptions="setGeoJSONSourceForRequestOptions"
:change:setGeoJSONSourceForRequestOptions="mapbox.changeSetGeoJSONSourceForRequestOptions"
:setGeoJSONSourceDataOptions="setGeoJSONSourceDataOptions"
:change:setGeoJSONSourceDataOptions="mapbox.changeSetGeoJSONSourceDataOptions"
:setVectorTileSourceTilesOptions="setVectorTileSourceTilesOptions"
:change:setVectorTileSourceTilesOptions="mapbox.changeSetVectorTileSourceTilesOptions"
:addLayerOptions="addLayerOptions"
:change:addLayerOptions="mapbox.changeAddLayerOptions"
:setFilterOptions="setFilterOptions"
:change:setFilterOptions="mapbox.changeSetFilterOptions"
:setPaintPropertyOptions="setPaintPropertyOptions"
:change:setPaintPropertyOptions="mapbox.changeSetPaintPropertyOptions"
:setLayoutPropertyOptions="setLayoutPropertyOptions"
:change:setLayoutPropertyOptions="mapbox.changeSetLayoutPropertyOptions"
:removeOptions="removeOptions"
:change:removeOptions="mapbox.changeRemoveOptions"
:flyToOptions="flyToOptions"
:change:flyToOptions="mapbox.changeFlyToOptions"
/>
<!-- #endif -->
<!-- #ifndef APP-PLUS || H5 -->
<view class="empty wrap">非 APP、H5 环境不支持</view>
......
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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论