最近,我能够更深入地研究上述问题,并实际上找到了一个对我的用例来说足够好的解决方案。有几种解决方案可以克服这个问题。
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 并向其添加功能的解决方案。但是,我找到了一些提示,可以让您开始关注此处和此处的链接