如何使用 React Native Mapbox 从集群中获取叶子?

How to get the leaves from a cluster using react native mapbox?

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

我正在显示一张全屏地图,其中包含一些用于缩放和以用户位置为中心的按钮。在这张地图上有几个'points of interest'。目前,我使用 ShapeSource 对数据进行聚类,对单个数据使用 SymbolLayer,对聚类 'points of interest' 使用 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,它包含一个簇中包含的所有特征或叶子。

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

最近,我能够更深入地了解上述问题,并实际上得出了一个足以满足我的用例的解决方案。有几种可能的解决方案来克服这个问题。

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

2) 分叉 Mapbox repro 并添加一个从原生 SDK

调用 getClusterLeaves() 方法的方法

解决方案 1

第一个解决方案使用 Supercluster npm 包,此解决方案完全基于 this page 上找到的信息。我将分享我最终得到的代码,但要了解更多信息,我想鼓励您阅读链接的资源。

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

Supercluster 的加载方法中使用的集合变量应该表示一个FeatureCollection 值。您可以通过多种方式创建。对我来说效果很好的是下面的那个。

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

groupFeatures 变量可以是由要在地图上显示的要素组成的数组。为了便于访问,我在继续之前将集群变量存储在我的状态中。我喜欢把事情分开,这样我就很容易看出代码的哪一部分负责什么。所以我的 Render 方法如下所示。

<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>

下一步是使用 supercluster 获取实际的集群,为此我们需要我们正在显示的地图的边界和当前的缩放级别(使用 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>
 );
}

所以现在对于拼图的最后一块,我们能够得到一个簇的实际叶子。在上面代码的最后一部分,我已经为 onPress 添加了 onMarkerPressed 方法。这是我们获得簇的叶子。

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 并向其添加功能的解决方案。然而,我发现了一些指导,可以帮助您开始遵循 link here and here