MapBoxMap 之 SymbolLayer实现标记聚合

注:这是个基础实验版,如果要使用需自行再研究研究,修改修改

一、准备实体

1.MapGeoJson(Gosn转换而来我自己再改改而来的)

/**
 * https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson
 */
public class MapGeoJson {
    /**
     * type : FeatureCollection
     * crs : {"type":"name","properties":{"name":"urn:ogc:def:crs:OGC:1.3:CRS84"}}
     * features : [{"type":"Feature","properties":{"id":"ak16994521","mag":2.3,"time":1507425650893,"felt":null,"tsunami":0},"geometry":{"type":"Point","coordinates":[-151.5129,63.1016,0]}},{"type":"Feature","properties":{"id":"ak16994519","mag":1.7,"time":1507425289659,"felt":null,"tsunami":0},"geometry":{"type":"Point","coordinates":[-150.4048,63.1224,105.5]}},{"type":"Feature","properties":{"id":"ak16994517","mag":1.6,"time":1507424832518,"felt":null,"tsunami":0},"geometry":{"type":"Point","coordinates":[-151.3597,63.0781,0]}}]
     */

    private String type = "FeatureCollection";
    private CrsBean crs;
    private List features;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public CrsBean getCrs() {
        return crs;
    }

    public void setCrs(CrsBean crs) {
        this.crs = crs;
    }

    public List getFeatures() {
        return features;
    }

    public void setFeatures(List features) {
        this.features = features;
    }

    public static class CrsBean {
        /**
         * type : name
         * properties : {"name":"urn:ogc:def:crs:OGC:1.3:CRS84"}
         */

        private String type = "name";
        private PropertiesBean properties;


        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public PropertiesBean getProperties() {
            return properties;
        }

        public void setProperties(PropertiesBean properties) {
            this.properties = properties;
        }

        public static class PropertiesBean {
            /**
             * name : urn:ogc:def:crs:OGC:1.3:CRS84
             */

            private String name = "urn:ogc:def:crs:OGC:1.3:CRS84";

            public String getName() {
                return name;
            }

            public void setName(String name) {
                this.name = name;
            }
        }
    }

    public static class FeaturesBean {
        /**
         * type : Feature
         * properties : {"type":0,"id":"ak16994521","mag":2.3,"time":1507425650893,"felt":null,"tsunami":0}
         * geometry : {"type":"Point","coordinates":[-151.5129,63.1016,0]}
         */

        private String type = "Feature";
        private PropertiesBeanX properties;
        private GeometryBean geometry;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public PropertiesBeanX getProperties() {
            return properties;
        }

        public void setProperties(PropertiesBeanX properties) {
            this.properties = properties;
        }

        public GeometryBean getGeometry() {
            return geometry;
        }

        public void setGeometry(GeometryBean geometry) {
            this.geometry = geometry;
        }

        public static class PropertiesBeanX {
            /**
             * id : ak16994521
             * mag : 2.3
             * time : 1507425650893
             * felt : null
             * tsunami : 0
             */
            private String id;
            private double mag;
            private long time;
            private Object felt;
            private int tsunami;


            public String getId() {
                return id;
            }

            public void setId(String id) {
                this.id = id;
            }

            public double getMag() {
                return mag;
            }

            public void setMag(double mag) {
                this.mag = mag;
            }

            public long getTime() {
                return time;
            }

            public void setTime(long time) {
                this.time = time;
            }

            public Object getFelt() {
                return felt;
            }

            public void setFelt(Object felt) {
                this.felt = felt;
            }

            public int getTsunami() {
                return tsunami;
            }

            public void setTsunami(int tsunami) {
                this.tsunami = tsunami;
            }
        }

        public static class GeometryBean {
            /**
             * type : Point
             * coordinates : [-151.5129,63.1016,0]
             */

            private String type = "Point";
            private List coordinates;

            public String getType() {
                return type;
            }

            public void setType(String type) {
                this.type = type;
            }

            public List getCoordinates() {
                return coordinates;
            }

            public void setCoordinates(List coordinates) {
                this.coordinates = coordinates;
            }
        }
    }

    /**
     * 生成Json字符串
     */
    public String crateJson() {
        Gson gson = new Gson();
        return gson.toJson(this);
    }
}

2.DemoObj(举个例子)

public class DemoObj {
    private String id;
    private double lat;
    private double lng;

    public DemoObj(String id, double lat, double lng) {
        this.id = id;
        this.lat = lat;
        this.lng = lng;
    }

    public String getId() {
        return id;
    }

    public double getLat() {
        return lat;
    }

    public double getLng() {
        return lng;
    }
}

二、ClusteringLayerManager(真正的核心类)

/**
 * 类描述:聚合数据管理类
 */
public class ClusteringLayerManager {
    private static final String MAP_SOURCE_ID = "map-source-id";
    private static final String CLUSTER_CIRCLE_ICON_ID = "clustered-circle-icon-id";
    private static final String UN_CLUSTERED_POINTS = "un-clustered-points";
    private static final String CLUSTER_ = "cluster-";
    private static final String COUNT = "count";
    private static final String POINT_COUNT = "point_count";
    private static final String PROPERTY_ID = "id";

    private Style loadedMapStyle;
    private GeoJsonSource geoJsonSource = null;
    private final HashMap imageMap = new HashMap<>();


    public ClusteringLayerManager(Style mapStyle) {
        this.loadedMapStyle = mapStyle;
        initLayerIcons();
        initSource();
    }

    private void initLayerIcons() {
        //添加图片
        loadedMapStyle.addImage(CLUSTER_CIRCLE_ICON_ID, BitmapUtils.getBitmapFromDrawable(MyApplication.getInstance().getResources().getDrawable(R.drawable.ic_cluster)));
        loadedMapStyle.addImages(imageMap);
    }

    private void initSource() {
        //添加源
        geoJsonSource = new GeoJsonSource(MAP_SOURCE_ID, FeatureCollection.fromFeatures(new Feature[]{}),
                new GeoJsonOptions()
                        .withCluster(true)
                        .withClusterRadius(30)
        );
        loadedMapStyle.addSource(geoJsonSource);
        //Creating a SymbolLayer icon layer for single data/icon points
        loadedMapStyle.addLayer(new SymbolLayer(UN_CLUSTERED_POINTS, MAP_SOURCE_ID).withProperties(
                iconImage("{" + PROPERTY_ID + "}")
//                ,iconSize(
//                        division(
//                                get("mag"), literal(4.0f)
//                        )
//                )
        ));

        // Use the earthquakes GeoJSON source to create three point ranges.
        int[] layers = new int[]{150, 20, 0};

        for (int i = 0; i < layers.length; i++) {
            //Add clusters' SymbolLayers images
            SymbolLayer symbolLayer = new SymbolLayer(CLUSTER_ + i, MAP_SOURCE_ID);

            symbolLayer.setProperties(
                    iconImage(CLUSTER_CIRCLE_ICON_ID)
            );
            Expression pointCount = toNumber(get(POINT_COUNT));

            // Add a filter to the cluster layer that hides the icons based on "point_count"
            symbolLayer.setFilter(
                    i == 0
                            ? all(has(POINT_COUNT),
                            gte(pointCount, literal(layers[i]))
                    ) : all(has(POINT_COUNT),
                            gt(pointCount, literal(layers[i])),
                            lt(pointCount, literal(layers[i - 1]))
                    )
            );
            loadedMapStyle.addLayer(symbolLayer);
        }

        //Add a SymbolLayer for the cluster data number point count
        loadedMapStyle.addLayer(new SymbolLayer(COUNT, MAP_SOURCE_ID).withProperties(
                textField(Expression.toString(get(POINT_COUNT))),
                textSize(15f),
                textColor(Color.WHITE),
                textIgnorePlacement(true),
                // The .5f offset moves the data numbers down a little bit so that they're
                // in the middle of the triangle cluster image
//                textOffset(new Float[] {0f, .5f}),
                textAllowOverlap(true)
        ));
    }

    //region 添加
    public void addClusteredGeoJsonSource(MapGeoJson mapGeoJson) {
        //先清除
        removeAllLayers();

        List features = mapGeoJson.getFeatures();
        if (!CheckUtil.checkList(features)) {
            return;
        }
        //添加单个头像
        for (MapGeoJson.FeaturesBean featuresBean : features) {
            MapGeoJson.FeaturesBean.PropertiesBeanX properties = featuresBean.getProperties();
            imageMap.put(properties.getId(), BitmapUtils.getBitmapFromDrawable(MyApplication.getInstance().getResources().getDrawable(R.drawable.mapbox_marker_icon_default)));
        }
        loadedMapStyle.addImages(imageMap);
        geoJsonSource.setGeoJson(FeatureCollection.fromJson(mapGeoJson.crateJson()));
    }
    //endregion

    //region 删除

    /**
     * 删除源
     */
    public void removeAllLayers() {
        imageMap.clear();
        if (geoJsonSource != null) {
            geoJsonSource.setGeoJson(FeatureCollection.fromFeatures(new Feature[]{}));
        }
    }
    //endregion
}

 

三、ClusterActivity(写个界面实现一下)

1.代码

public class ClusterActivity extends AppCompatActivity {
    private MapView mapView;
    private ClusteringLayerManager clusteringLayerManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       //初始化 Mapbox
        Mapbox.getInstance(this, getString(R.string.mapbox_access_token));
        setContentView(R.layout.activity_cluster);
        mapView = findViewById(R.id.cluster_map);
        mapView.onCreate(savedInstanceState);
        mapView.getMapAsync(mapboxMap -> {
            mapboxMap.setStyle(Style.MAPBOX_STREETS, style -> {
                mapReady(style);
            });
        });
    }

    private void mapReady(@NonNull Style style) {
        clusteringLayerManager = new ClusteringLayerManager(style);
    }

    public void add(View view) {
        List demoObjList = new ArrayList<>();
        Random random = new Random();
        int lat = random.nextInt(79);
        int lng = random.nextInt(179);
        for (int i = 0; i < 100; i++) {
            DemoObj demoObj = new DemoObj("id" + i, lat + 0.001 * i, lng - 0.001 * i);
            demoObjList.add(demoObj);
        }
        MapGeoJson mapGeoData = getMapGeoData(demoObjList);
        clusteringLayerManager.addClusteredGeoJsonSource(mapGeoData);
    }

    public void clear(View view) {
        clusteringLayerManager.removeAllLayers();
    }

    private MapGeoJson getMapGeoData(List demoObjList) {
        MapGeoJson mapGeoJson = new MapGeoJson();
        List featureList = new ArrayList<>();
        //填充数据
        for (DemoObj demoObj : demoObjList) {
            MapGeoJson.FeaturesBean fBean = new MapGeoJson.FeaturesBean();
            fBean.setProperties(getDevicePropertiesBeanX(demoObj.getId()));
            fBean.setGeometry(getGeometryBean(demoObj.getLat(), demoObj.getLng()));
            featureList.add(fBean);
        }
        mapGeoJson.setFeatures(featureList);
        return mapGeoJson;
    }

    private MapGeoJson.FeaturesBean.GeometryBean getGeometryBean(double lat, double lng) {
        MapGeoJson.FeaturesBean.GeometryBean geometryBean = new MapGeoJson.FeaturesBean.GeometryBean();
        List coordinates = new ArrayList<>();
        coordinates.add(lng);
        coordinates.add(lat);
        geometryBean.setCoordinates(coordinates);
        return geometryBean;
    }

    private MapGeoJson.FeaturesBean.PropertiesBeanX getDevicePropertiesBeanX(String id) {
        MapGeoJson.FeaturesBean.PropertiesBeanX pBeanX = new MapGeoJson.FeaturesBean.PropertiesBeanX();
        pBeanX.setId(id);
        return pBeanX;
    }

    //region 生命周期
    @Override
    protected void onStart() {
        super.onStart();
        if (mapView != null) {
            mapView.onStart();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (mapView != null) {
            mapView.onResume();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        if (mapView != null) {
            mapView.onPause();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mapView != null) {
            mapView.onStop();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mapView != null) {
            mapView.onDestroy();
        }
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        if (mapView != null) {
            mapView.onLowMemory();
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (mapView != null) {
            mapView.onSaveInstanceState(outState);
        }
    }
    //endregion
}

 

2.布局 R.layout.activity_cluster




    

四、看看效果

MapBoxMap 之 SymbolLayer实现标记聚合_第1张图片MapBoxMap 之 SymbolLayer实现标记聚合_第2张图片

你可能感兴趣的:(MapBoxMap,地图使用指南)