代码之家  ›  专栏  ›  技术社区  ›  xarlymg89 MiguelSlv

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

  •  1
  • xarlymg89 MiguelSlv  · 技术社区  · 6 年前

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

    我需要在Android上以本机方式显示数千(而不是数百万)个交互点(或标记)。我只需要能够捕获单击的点/标记。

    我成功地在Android的Mapbox上实现了标记。但我不喜欢缩小手机时显示这么多标记的结果。

    在传单中有一个很棒的插件,叫做Markercluster,它将一个圆圈分组,圆圈下面有一个隐藏的标记。我发现这个解决方案非常完美。

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

    因此,简单介绍一下,标记缺少GeoJSON点的外观(当我缩小时隐藏或放大时显示,在我这样做时或多或少显示)。但是,标记允许我单击它们。

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

    1 回复  |  直到 6 年前
        1
  •  2
  •   xarlymg89 MiguelSlv    6 年前

    很显然,有一种方法可以实现我使用Android SDK的Mapbox的目的。方法是这样的:

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

    1、使用GeoJson文件加载点(标记)(添加数据源)

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

    2、包括标记图标(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、将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、添加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符号层的一个好方法。你可以用它做很多好事。