考虑到 Mapbox-gl 的当前版本,这是一个有点复杂的解决方案0.37.0
.
我试图在用户单击群集时显示所有标记
鉴于这一陈述,有两种可能的解决方案。
- 在下一个缩放级别显示标记和簇或
- 显示所有标记(无论缩放级别如何)。
In mapbox-gl
,聚类功能由超星团 https://github.com/mapbox/supercluster.
As of 0.37.0
,当您通过以下方式设置源时,没有直观的 API 可以自定义超级集群的工作方式map.addSource...
因此,您可能需要在入口文件中使用/导入 supercluster 作为库依赖项,其中mapbox-gl
使用(通过 npm 或其他方式)。
1. 使用超聚类来查找标记非聚类时的下一个缩放级别。
在超集群中,可以使用以下方法getClusterExpansionZoom(clusterId, clusterZoom)
,这为您提供了所选簇的下一个缩放,从中可以看到标记(无论是1,2,4,n
zoomlevels
from currentZoomLevel
.
var supercluster = require('supercluster');
let features;
map.on('load', function(e) {
features = supercluster().load(FEATURES);
});
// helper function
function findNearestCluster(map, marker, i) {
let clusterSelected = marker;
// get bounds
let south = map.getBounds()._sw;
let north = map.getBounds()._ne;
let bounds = [south.lng, south.lat, north.lng, north.lat];
let currentClusters = i.getClusters(bounds, Math.floor(map.getZoom()));
let compare = {
lng: clusterSelected.geometry.coordinates[0],
lat: clusterSelected.geometry.coordinates[1]
};
let minClusters = currentClusters.map(cluster => {
let lng = cluster.geometry.coordinates[0];
let lat = cluster.geometry.coordinates[1];
return {
id: cluster.properties.cluster_id,
geometry: cluster.geometry,
value: Math.pow(compare.lng - lng,2) * Math.pow(compare.lat-lat,2)
};
});
return minClusters.sort(function(a,b) {
return a.value - b.value;
});
}
map.on('click', function (e) {
var cluster_features = map.queryRenderedFeatures(e.point, {
layers: [
'cluster-0',
'cluster-1',
'cluster-2'
]
});
var cluster_feature = cluster_features[0];
// we need to find the nearest cluster as
// we don't know the clusterid associated within supercluster/map
// we use findNearestCluster to find the 'nearest'
// according to the distance from the click
// and the center point of the cluster at the respective map zoom
var clusters = findNearestCluster(map, cluster_feature, features);
var nearestCluster = clusters[0];
var currentZoom = Math.floor(map.getZoom());
var nextZoomLevel = supercluster()
.getClusterExpansionZoom(nearestCluster.id, currentZoom);
if (cluster_feature && cluster_feature.properties.cluster) {
map.jumpTo({
around: e.lngLat,
zoom: nextZoomLevel
});
}
});
2. 显示所有标记(无论缩放级别如何)。
我们做了与上面类似的事情,但不只是使用nextZoomLevel
/ getClusterExpansionZoom
,我们可以使用getLeaves
.
getLeaves 返回集群中的所有标记 -
var clusters = findNearestCluster(map, cluster_feature, features);
var nearestCluster = clusters[0];
var currentZoom = Math.floor(map.getZoom());
var getLeaves = supercluster()
.getLeaves(nearestCluster.id, currentZoom, Infinity);
从这里,您可以将叶子渲染为mapbox.Markers
如果需要,类似于leaflet.markercluster
.
第二种解决方案的问题是,每当视图发生更改时,您都需要删除/更新标记,以便反映地图视图的当前位置。
从自上而下的角度来看,这是可以的,但如果你开始旋转,视图渲染会有点卡顿,所以从 UI 角度来看我不建议这样做。