Mapbox GL群集缩放

我试图在用户点击群集时显示所有标记.

这是我到目前为止所做的:

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级缩放.它有效,但有时我需要进一步缩放以查看标记.

有关如何通过单击缩放到实际标记的任何建议?

最佳答案 鉴于当前版本的Mapbox-gl 0.37.0,这是一个复杂的解决方案.

I’m trying to show all the markers when the user click on a cluster

给出这一陈述有两种可能的解决方案.

>在下一个缩放级别显示标记和聚类
>显示所有标记(与缩放级别无关).

在mapbox-gl中,群集功能由supercluster提供.

从0.37.0开始,没有直观的API来定制通过map.addSource设置源代码时超级集群的工作方式…

因此,您可能需要在使用mapbox-gl的条目文件中使用/ import supercluster作为库依赖项(通过npm或其他方式).

1.使用超级集群查找标记取消群集时的下一个缩放级别.

在超级集群中,您可以使用方法getClusterExpansionZoom(clusterId,clusterZoom),这将为您提供所选集群的下一个缩放,从中可以看到标记(无论是1,2,4,还是来自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.

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.

第二种解决方案的问题是,只要视图被更改,您就需要删除/更新标记,以反映mapview的当前位置.

从上到下的角度来看,这没关系,但是如果你开始透视,那么视图渲染会有点凹凸不平,所以我不建议从UI的角度来看.

点赞