如何使用React Native Mapbox获取聚类中的叶子?

3

目前我正在做一个需要使用react-native的项目。考虑到Mapbox Android SDK中如何处理这个问题,我面临的问题似乎很简单。情况是这样的:

我正在显示一个全屏地图,上面有一些用于缩放和定位用户位置的按钮。在这张地图上,有几个“兴趣点”。目前,我正在使用ShapeSource为数据聚类,并使用一个SymbolLayer来表示单个兴趣点,以及一个SymbolLayer来表示聚类的“兴趣点”。

我想要实现的是,当我点击其中一个聚类时,可以访问该聚类中所有叶子节点。在Android SDK中,可以使用以下代码实现:

 String[] layers = new String[] {"cluster-route-0", "cluster-route-1", "cluster-route-2", "cluster-route-3", "cluster-route-4"};


 features = mMapboxMap.queryRenderedFeatures(pixel, layers);
 GeoJsonSource source = mMapboxMap.getStyle().getSourceAs(ROUTE_SOURCE_ID);

然后我将循环遍历所有功能,并获取簇叶子,就像这样:
for (Feature feature : features) {
   FeatureCollection collection = source.getClusterLeaves(feature, 100,0);
}

那么,集合变量将是一个FeatureCollection,其中包含所有包含在群集中的要素或叶子。

查看文档,我没有在React Native Mapbox版本中找到类似的东西。所以我想知道这里是否有人能够找到解决方案。或者,我可能已经在示例或文档中忽略了某些内容。

1个回答

2

最近我深入研究了上述问题,并找到了一个对我的用例来说足够好的解决方案。有几种解决方法可以克服这个问题。

1) 与Mapbox结合使用另一种集群解决方案,例如Supercluster

2) Fork Mapbox repro并添加一个调用本地SDK中getClusterLeaves()方法的方法

解决方案1

第一种解决方案使用了Supercluster npm包,这个解决方案完全基于此页面上的信息。我会分享我最终采用的代码,但是为了获得更多信息,我鼓励你阅读链接的资源。

//Initialize supercluster, these values worked great for me
const cluster = new Supercluster({ radius: 40, maxZoom: 16 });
cluster.load(collection.features);

在Supercluster的load方法中使用的集合变量应该代表一个FeatureCollection值。你可以用多种方式创建它。对我而言,效果良好的一种方式如下。

const collection = MapboxGL.geoUtils.makeFeatureCollection(groupFeatures);

groupFeatures变量可以是包含要显示在地图上的特征的数组。为了便于访问,我已经将cluster变量存储在我的状态中。我喜欢保持事物的独立性,这样我就可以轻松地看到代码的哪个部分负责什么。因此,我的渲染方法如下所示。

<MapboxGL.MapView
  ref={c => (this._map = c)}
  onRegionDidChange={this.updateClusters}
  zoomEnabled
  style={[{ flex: 1 }]}>

 //This is where we render the clusters
 {this.renderPoints()}

</MapboxGL.MapView>

下一步是使用超级聚类获取实际的聚类,为此我们需要地图的边界和当前缩放级别(使用Math.round,因为小数值可能会导致超级聚类中的错误)。
const bounds = await this._map.getVisibleBounds();
const zoom = Math.round(await this._map.getZoom());
const westLng = bounds[1][0];
const southLat = bounds[1][1];
const eastLng = bounds[0][0];
const northLat = bounds[0][1];

现在我们可以通过像这样的方式检索实际的集群:

const sc = this.state.superCluster;
const clusters = sc.getClusters(
    [westLng, southLat, eastLng, northLat],
    zoom
)
this.setState({clusters: clusters})

现在我们可以在Mapbox Shapesource中呈现聚类。

renderPoints = () => {
  const { clusters } = this.state;
  return (
   <MapboxGL.ShapeSource
     id="symbolLocationSource"
     hitbox={{ width: 18, height: 18 }}
     onPress={this.onMarkerSelected}
     shape={{ type: "FeatureCollection", features: superClusterClusters }}
    >
    <MapboxGL.SymbolLayer
     id="pointCount"
     minZoomLevel={6}
     style={mapStyles.clusterCount}
    />

    <MapboxGL.CircleLayer
     id="clusteredPoints"
     minZoomLevel={6}
     belowLayerID="pointCount"
     filter={[">", "point_count", 1]}
     style={mapStyles.clusteredPoints}
    />

    <MapboxGL.SymbolLayer
     id="symbolLocationSymbols"
     minZoomLevel={6}
     filter={["!", ["has", "point_count"]]}
     style={mapStyles.icon}
    />
   </MapboxGL.ShapeSource>
 );
}

现在是拼图的最后一块,我们能够获得聚类的实际叶子。在上面的代码的最后一部分中,我已经添加了onMarkerPressed方法作为onPress的处理程序。这是我们获取聚类叶子的地方。

onMarkerSelected = event => {
  const point = event.nativeEvent.payload;
  const { name, cluster } = point.properties;

  if (cluster) {
    const sc = this.state.superCluster;
    const points = sc
      .getLeaves(point.properties.cluster_id, Infinity)
    //This will output an array with all leaves of the selected cluster
    console.log(points);
  }
}

解决方案2

所以上述提到的解决方案是我选择的解决方案,因此我没有探索将功能添加到Mapbox repro中的解决方案。但是,我找到了一些指针,可以让您开始遵循这里这里的链接。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接