与 Mapbox 上数千个标记(或 GeoJSON 点)的交互 Android

Interaction with thousands of markers (or GeoJSON points) on Mapbox Android

我确定我在 Mapbox 实现中可能遗漏了一些东西,因为我一直在研究很多替代方案(Tangram ES、Mapzen 和其他)。

我需要在 Android 数千(而不是数百万)个交互点(或标记)上进行本地显示。我只需要能够捕获点击了哪个 point/marker。

我成功地在 Mapbox 上为 Android 实现了标记。但是我不喜欢当我缩小 phone.

时显示这么多标记的结果

在 Leaflet 中,有一个很棒的插件,称为 Markercluster,它将隐藏的标记分组在一个圆圈中。我发现该解决方案非常完美。

我找不到适用于 Mapbox(或其他 API)的类似解决方案。到目前为止,我发现唯一接近我正在寻找的东西是在 Mapbox 上加载 GeoJSON 文件。而且它简单易行。以后很容易隐藏图层。但是我无法知道点击了哪个点,所以我可以加载与该点相关的信息并将其显示在屏幕上。

所以,简报,标记缺乏我通过 GeoJSON 点获得的外观(当我缩小时隐藏或放大时显示,或多或少地显示)。但是,标记允许我点击它们。

P.S。如果有人知道 Mapbox 的替代品,可以根据需要显示 POI(兴趣点),请告诉我。我很乐意给它一个机会。

好吧,显然有一种方法可以使用 Mapbox for Android SDK 来实现我的意图。方法是这样的:

  1. 使用 GeoJson 文件加载点(标记)(添加数据源)
  2. 包括标记的图标(Mapbox 提供了广泛的默认标记 https://www.mapbox.com/maki-icons/
  3. 将 GeoJson 点与图标相关联(因此每个点至少与一个图标相关,尽管您可能希望所有标记都使用相同的图标)(添加视觉表示)
  4. 添加一个 onClick 事件侦听器以检测点击了哪个点(添加交互性)

1.Load 使用 GeoJson 文件的点(标记)(添加数据源)

URL geoJsonUrl = new URL("https://your-website.com/list.json");
final GeoJsonSource geoJsonSource = new GeoJsonSource("geojson-source", geoJsonUrl);
mapboxMap.addSource(geoJsonSource);

2.Include 标记图标(Mapbox 提供了广泛的默认标记 https://www.mapbox.com/maki-icons/)(添加视觉表示)

Bitmap marker_type1_icon = BitmapFactory.decodeResource(getResources(), R.drawable.marker_type1_icon);
mapboxMap.addImage("marker_type1", marker_type1_icon);
Bitmap marker_type2_icon = BitmapFactory.decodeResource(getResources(), R.drawable.marker_type2_icon);
mapboxMap.addImage("marker_type2", marker_type2_icon);

3.Relate GeoJson 指向图标(因此每个点至少与一个图标相关,可能是您希望所有标记都使用相同的图标)(添加视觉表示)

SymbolLayer symbolLayer = new SymbolLayer("layer-id", "geojson-source");
symbolLayer.setProperties(
    // This is the bit that makes the map to display an icon or another. "poi" is a property of a Point in a GeoJSON document.
    // If you enclosed between keys,, it will introduce the value of the poi property.
    // If you want a fixed icon for all markers, change this for "marker_type1", following my example from point 2.
    PropertyFactory.iconImage("{poi}"),
    // With this property we will show which Point was clicked, making the icon look bigger
    PropertyFactory.iconSize(
        Function.property(
            "selected",
            Stops.categorical(
                Stop.stop(true, PropertyFactory.iconSize(2.0f)),
                Stop.stop(false, PropertyFactory.iconSize(1.0f))
            )
        )
    )
);
mapboxMap.addLayer(symbolLayer);

4.Add 一个 onClick 事件侦听器,用于检测点击了哪个点(添加交互性)

mapboxMap.addOnMapClickListener(new MapboxMap.OnMapClickListener() {
    @Override
    public void onMapClick(LatLng point) {
        PointF screenPoint = mapboxMap.getProjection().toScreenLocation(point);
        List<Feature> features = mapboxMap.queryRenderedFeatures(screenPoint, "layer-id");
        if (!features.isEmpty()) {
            Feature selectedFeature = features.get(0);
            selectedFeature.getProperties().addProperty("selected", true);
            String title = selectedFeature.getStringProperty("title");
            Toast.makeText(MapActivity.this, "You selected " + title, Toast.LENGTH_SHORT).show();

            // This triggers the update of the feature (Point) on the data source so it updates the SymbolLayer and you can see the feature enabled (bigger in this example)
            geoJsonSource.setGeoJson(selectedFeature);
        }
    }
});

我找到的完整指南是这个 https://blog.mapbox.com/a-guide-to-the-android-symbollayer-api-5daac7b66f2c,它非常棒,尽管一两个功能已被弃用,我正在寻找它们的替代品。除此之外,这可能是深入了解 Mapbox SDK 的 SymbolLayer 的好方法。你可以用它做一些很棒的事情。