作者:刘大
使用背景
需要在前端动态更改地图样式,并高效进行鼠标交互获取要素的业务场景时,我们会采取MVT矢量瓦片来解决此类问题,但是web应用开发已经选用Leaflet地图框架的情况下怎么办呢,这时,我们便可以引入“leaflet-mapbox-gl”插件,那具体怎么实现捏,接下来我们就详细阐述下具体的使用流程
具体使用流程
1.引入相关库
在原有引入的leaflet先关库的基础上,还需引入mapboxgl的js以及css文件以及leaflet-mapbox-gl的js文件
//引入mapbox-gl-enhance,解决原生只支持3857坐标系的限制
<link rel="stylesheet" href="https://iclient.supermap.io/web/libs/mapbox-gl-js-enhance/1.12.0/mapbox-gl-enhance.css">
<script type="text/javascript" src="https://iclient.supermap.io/web/libs/mapbox-gl-js-enhance/1.12.0/mapbox-gl-enhance.js">< /script>
// 引入leaflet-mapbox-gl 加载mvt矢量瓦片
<script type="text/javascript" src="https://iclient.supermap.io/web/libs/leaflet-mapbox-gl/0.0.15/leaflet-mapbox-gl.min.js">< /script>
同样也可以通过 https://iclient.supermap.io/download/download.html 该地址下载离线的三方库,获取离线文件进行加载
2.加载矢量瓦片
这块可参考iClinet范例 https://iclient.supermap.io/examples/leaflet/editor.html#mvt_mapboxgl
就不多加讲述,主要是注意以下两点
2.1设定Leaflet的crs
我们都知道MVT矢量瓦片是按照一定的比例尺级别出图的,那么为与mapboxgl的级别相匹配,leaflet的分辨率应设置为第0级为全球范围宽度除以瓦片宽度256
以4326坐标系为例:
// 常见坐标系第0级分辨率 WebMercator(3857):2*6378137*Math.PI/256 WGS84(4326):360.0/256 China2000(4490):360.0/256 Beijing54(4214):360.0/256 Xian80(4610):360.0/256
var topResolution = 360.0 / 256;
var resolutions = [];
for (var zoom = 0; zoom < 22; zoom++) {
resolutions.push(topResolution / Math.pow(2, zoom));
}
var crs = L.Proj.CRS('EPSG:4326', {
origin: [-180, 90],
resolutions: resolutions
});
2.2mapboxGL里的minZoom和maxZoom的设置
mapboxgl zoom 和leaflet zoom 相差一级
//leaflet:
map = L.map('map', {
center: [30, 105],
zoom: 5,
crs: crs,
minZoom: 5,
maxZoom: 14
})
//mapboxGL:
//设置图层背景为透明
style.layers[0].paint['background-color'] = 'rgba(168,209,221,0)';
var gl = L.mapboxGL({
renderWorldCopies: false,
style: style,
crs: 'EPSG:4326',
minZoom:4,
maxZoom: 13
}).addTo(map);
// 获取 mapboxgl 地图
mapboxglMap = gl.getMapboxMap();
3.鼠标交互,获取要素
有下面两种方式都可以实现
3.1 使用Leaflet的事件
使用时,需注意使用传入点的像素坐标为e.originalEvent.offsetX和e.originalEvent.offsetY
直接使用layerPoint会有偏移 导致获取的要素不准确
map.on('click',function (e){
console.log(e)
var features = mapboxglMap.queryRenderedFeatures([e.originalEvent.offsetX,e.originalEvent.offsetY])
if(mapboxglMap.getLayer('ss') === undefined){
mapboxglMap.addLayer({
"id": "ss",
"type": "fill",
"source": features[0].source,
"source-layer": features[0].sourceLayer,
"paint":{
"fill-color":'rgba(255,0,0,1)',
"fill-opacity":0.6
}
})
}
//也可根据其他属性字段进行过滤
mapboxglMap.setFilter("ss",["in", "$id", features[0].id])
3.2使用mapboxGL的事件
这里需要在初始化时,设置interactive为true
L.mapboxGL({
renderWorldCopies: false,
style: style,
crs: 'EPSG:4326',
interactive:true,
minZoom:4,
maxZoom: 13
}).addTo(map);
mapboxglMap.on('click',function (e){
var features = mapboxglMap.queryRenderedFeatures(e.point)
if(mapboxglMap.getLayer('ss') === undefined){
mapboxglMap.addLayer({
"id": "ss",
"type": "fill",
"source": features[0].source,
"source-layer": features[0].sourceLayer,
"paint":{
"fill-color":'rgba(255,0,0,1)',
"fill-opacity":0.6
}
})
}
//也可根据其他属性字段进行过滤
mapboxglMap.setFilter("ss",["in", "$id", features[0].id])
})
注册mouseover等其他鼠标交互事件 也同样如此