如何使用 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
目前我正在做一个需要我使用 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