目前比较成熟的模式就是使用maplibre-gl-leaflet和mapbox-gl-leaflet
其实现原理就是把maplibregl或mapboxgl创建的矢量图层以图层方式叠加到leaflet地图上
目前以maplibregl(V4.1.1)方案最佳,因为mapboxgl的图层叠加到leaflet地图上时,在层级小于4的时候,会出现明显偏移现象,而且mapboxgl(V2.15.0)地图开启交互时,移动地图会出现明显卡顿。因此,推荐使用maplibre+maplibre-gl-leaflet来实现leaflet加载矢量图层。
一般情况下,在maplibregl图层上注册鼠标和键盘事件是不推荐的,interactive默认为false。那么我要实现与矢量图层的交互应该怎么来实现呢
众所周知,矢量图层的要素是加载数据到前端渲染的,这些数据是可以直接在前端获取的,如果我要实现点击矢量图层获取要素属性,不开启图层interactive该如何实现?
解决办法就是使用leaflet交互事件+maplibregl的API
。
以下是一个示例
https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/#queryrenderedfeatures
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Leaflet VectorLayer Demo</title>
<!-- Leaflet -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.0/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.9.0/dist/leaflet.js"></script>
<!-- Maplibre GL -->
<link href='https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.css' rel='stylesheet' />
<script src='https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.js'></script>
<script src="https://unpkg.com/@maplibre/maplibre-gl-leaflet@0.0.20/leaflet-maplibre-gl.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
const map = L.map('map', {
attributionControl: false,
}).setView([23, 113], 5);
const tiles = L.tileLayer(
'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
{
maxZoom: 19,
}
);
const mbTiles = L.maplibreGL(
{
style: 'https://demotiles.maplibre.org/style.json', // maplibregl style URL
}
).addTo(map);
map.on("click", evt => {
// console.log('leaflet', evt)
let point = [evt.originalEvent.offsetX, evt.originalEvent.offsetY];
let features = mbTiles.getMaplibreMap()?.queryRenderedFeatures(point);
if (!features || !features.length) {
console.warn("未查询到要素!");
return
}
console.log(features[0])
})
L.control.layers({ 矢量图: mbTiles, 卫星图: tiles }).addTo(map);
</script>
</body>
</html>