Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
basic-uniapp-v3
概览
概览
详情
活动
周期分析
版本库
存储库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Basic
basic-uniapp-v3
Commits
1fa947a8
提交
1fa947a8
authored
8月 22, 2023
作者:
方治民
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 实现地图组件的相关常用方法
上级
80e4188f
显示空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
625 行增加
和
63 行删除
+625
-63
hook.ts
src/components/Map/Mapbox/hook.ts
+36
-0
index.ts
src/components/Map/Mapbox/index.ts
+216
-57
index.vue
src/components/Map/Mapbox/index.vue
+234
-4
mapbox.module.js
src/components/Map/Mapbox/mapbox.module.js
+139
-2
没有找到文件。
src/components/Map/Mapbox/hook.ts
浏览文件 @
1fa947a8
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
}
`
}
src/components/Map/Mapbox/index.ts
浏览文件 @
1fa947a8
...
...
@@ -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
(
''
)
},
}
src/components/Map/Mapbox/index.vue
浏览文件 @
1fa947a8
...
...
@@ -11,17 +11,45 @@
// 1. 通过在逻辑层 data 中设置的属性向视图层传递数据
// 2. 通过在逻辑层 methods 定义方法,在视图层调用传递参数(注意:只能传递可进行 JSON 序列化的数据)
function
n
ail
()
{}
function
n
oop
()
{}
export
default
{
emits
:
[
'register'
],
data
()
{
return
{
id
:
nanoid
(),
onLoaded
:
n
ail
,
onLoaded
:
n
oop
,
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>
...
...
src/components/Map/Mapbox/mapbox.module.js
浏览文件 @
1fa947a8
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
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论