Mapbox GL群集缩放

时间:2016-05-26 11:49:06

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

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

3 个答案:

答案 0 :(得分:1)

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

  

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

鉴于这一陈述,有两种可能的解决方案。

  1. 在下一个缩放级别或
  2. 中显示标记和群集
  3. 显示所有标记(与缩放级别无关)。
  4. mapbox-gl中,群集功能由supercluster提供。

    0.37.0开始,没有直观的API来自定义当您通过map.addSource...

    设置来源时超级集群的工作方式

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

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

    在超级集群中,您可以使用方法getClusterExpansionZoom(clusterId, clusterZoom),这样您就可以看到所选群集的下一个缩放,从中可以看到标记(1,2,4,n zoomlevels来自{{ 1}}。

    currentZoomLevel

    <强> 2。显示所有标记(与缩放级别无关)。

    我们执行与上面类似的操作,但我们可以使用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 }); } }); 而不是仅使用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

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

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

答案 1 :(得分:0)

如果您从cluster_features中的每个点的坐标构造了一个lineString然后执行了zoomTo-lingstring

,该怎么办?

答案 2 :(得分:0)

如@MeltedPenguin所说(在MapBox - Cluster Zooming中)。您无需使用var http_util = function (type, url, params, headers, success_handler, error_handler, base_url) { if(base_url) { url = base_url + url; } var success = arguments[3]?arguments[3]:function(){}; var error = arguments[4]?arguments[4]:function(){}; $.ajax({ type: type, url: url, dataType: 'json', data: params, headers: headers, username: name, password: password, success: function (data, textStatus, xhr) { if(textStatus === 'success'){ success(xhr.code, data) } }, error: function (xhr, error_text, statusText) { error(xhr.code, xhr); } }) } 就可以做到。我搜索了几个答案,最后使用coffeescript做了自己的解决方案(您可以使用http://js2.coffee/之类的工具将其转换回JS):

SuperCluster

在我的页面上,我有两个基于相同数据源但具有不同属性的图层。一个定义所有点(无簇),另一个定义点和簇。 对于我的显示,我使用带有簇的“ markers_layer”,为了计算距离和东西,我使用另一个作为点的DB。

来源:

    @clusterRadius = 30
    @map.on 'click', (e) =>
          features = @map.queryRenderedFeatures(e.point, { layers: ['markers_layer'] });
          if features && features.length > 0
            if features[0].properties.cluster
              cluster = features[0].properties

              allMarkers = @map.queryRenderedFeatures(layers:['markers_layer_dot']);
              self = @ #just a way to use 'this' un a function, its more verbose then =>    

              #Get all Points of a Specific Cluster
              pointsInCluster = allMarkers.filter((mk) ->
                pointPixels = self.map.project(mk.geometry.coordinates) #get the point pixel
                #Get the distance between the Click Point and the Point we are evaluating from the Matrix of All point
                pixelDistance = Math.sqrt((e.point.x - (pointPixels.x)) ** 2 + (e.point.y - (pointPixels.y)) ** 2)

                #If the distant is greater then the disance that define a cluster,  then the point si in the cluster
                # add it to the boundaries
                Math.abs(pixelDistance) <= self.clusterRadius
              )

              #build the bounding box with the selected points coordinates
              bounds = new (mapboxgl.LngLatBounds)
              pointsInCluster.forEach (feature) ->
                bounds.extend feature.geometry.coordinates
                return

              #Move the map to fit the Bounding Box (BBox)
              @map.fitBounds bounds, {padding:45, maxZoom: 16}

            else
              window.open('/en/ad/' + features[0].properties.propertyId)

图层:

  @map.addSource "markers_source_wo_cluster",
    type: "geojson"
    data:
      type: "FeatureCollection"
      features: []
    cluster: false
    clusterMaxZoom: 10
    clusterRadius: @clusterRadius

  @map.addSource "markers_source",
    type: "geojson"
    data:
      type: "FeatureCollection"
      features: []
    cluster: true
    clusterMaxZoom: 60
    clusterRadius: @clusterRadius