最近我深入研究了上述问题,并找到了一个对我的用例来说足够好的解决方案。有几种解决方法可以克服这个问题。
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.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)
console.log(points);
}
}
解决方案2
所以上述提到的解决方案是我选择的解决方案,因此我没有探索将功能添加到Mapbox repro中的解决方案。但是,我找到了一些指针,可以让您开始遵循这里和这里的链接。