Mapbox GL群集缩放 [英] Mapbox GL cluster zoom
问题描述
当用户单击集群时,我试图显示所有标记.
I'm trying to show all the markers when the user click on a cluster.
这是我到目前为止所做的:
This is what I have done so far:
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];
if (cluster_feature && cluster_feature.properties.cluster) {
map.jumpTo({
around: e.lngLat,
zoom: map.getZoom() + 2
});
}
});
每次用户单击标记时,这将添加2级缩放.它可以正常工作,但有时我需要进行更大的缩放才能看到标记.
This is adding 2 levels of zoom every time the user click on a marker. It works but sometimes I need to zoom even more to see the markers.
关于我如何单击即可放大实际标记的任何建议?
Any suggestion about how I could zoom to the actual markers with a single click?
推荐答案
考虑到当前版本的Mapbox-gl 0.37.0
,这有点复杂.
This is a bit of a complicated solution given the current version of Mapbox-gl 0.37.0
.
当用户单击集群时,我试图显示所有标记
I'm trying to show all the markers when the user click on a cluster
根据这一陈述,有两种可能的解决方案.
There are two possible solutions given this one statement.
- 在下一个缩放级别显示标记以及聚类,或者
- 显示所有标记(与缩放级别无关).
在mapbox-gl
中,集群功能由超级集群提供.
In mapbox-gl
, the clustering functionality is provided by supercluster.
从0.37.0
开始,当您通过map.addSource...
因此,在使用mapbox-gl
的条目文件中(通过npm或其他方式),您可能需要使用/导入超级集群作为库依赖项.
therefore you may need to use/import supercluster as a library dependency in your entry file where mapbox-gl
is used (either via npm or otherwise).
1.使用超级群集查找标记取消群集时的下一个缩放级别.
在超级集群中,可以使用方法getClusterExpansionZoom(clusterId, clusterZoom)
,这将为您提供所选集群的下一个缩放,从中可以看到标记(是否是currentZoomLevel
中的1,2,4,n
zoomlevels
.
In supercluster, you can use the method getClusterExpansionZoom(clusterId, clusterZoom)
, this gives you the next zoom for the selected cluster from where markers can be seen (whether that is 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.显示所有标记(与缩放级别无关).
我们执行与上述类似的操作,但是我们可以使用getLeaves
.而不是仅使用nextZoomLevel
/getClusterExpansionZoom
.
We do the a similar thing as above, but instead of using just nextZoomLevel
/ getClusterExpansionZoom
, we can use the getLeaves
.
getLeaves返回集群中的所有标记-
getLeaves returns all markers from the cluster -
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
.
From here, you can render the leaves as mapbox.Markers
if required, similar to leaflet.markercluster
.
第二种解决方案的问题是,只要视图已更改,就需要删除/更新标记,以反映地图视图的当前位置.
The problem with the second solution is that you need to remove/update the markers whenever the view has been changed, in order to reflect the current position of the mapview.
从上到下的角度来看,这是可以的,但是,如果您开始旋转,则视图渲染会有点刺痛,因此从UI的角度来看,我不建议这样做.
From a top-down perspective, this is ok, but if you start pivoting, the view render gets a bit jank, so I wouldn't recommend that from a UI perspective.
这篇关于Mapbox GL群集缩放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!