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 变体中找不到类似的东西。所以我想知道这里是否有人能够找到解决方案。或者,也许我忽略了示例或文档中的某些内容。

4

1 回答 1

1

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

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

getClusterLeaves()2) fork Mapbox repro 并添加一个从原生 SDK调用该方法的方法

解决方案 1

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

//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,因为十进制值可能会导致 supercluster 中的错误)。

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 并向其添加功能的解决方案。但是,我找到了一些提示,可以让您开始关注此处和此处的链接

于 2019-10-16T11:57:40.517 回答