mapbox 聚合图

本文介绍了一个使用Mapbox GL JS创建的交互式地图应用,该应用能够处理并可视化大量的地震数据。通过实现点的聚类,地图能高效地展示全球范围内的地震分布情况,并允许用户通过点击聚合点来查看更详细的地震信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<!DOCTYPE html>
<html>

<head>
    <meta charset='utf-8' />
    <title>聚合图</title>
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
    <link href="https://api.mapbox.com/mapbox-gl-js/v2.8.2/mapbox-gl.css" rel="stylesheet">
    <script src="https://api.mapbox.com/mapbox-gl-js/v2.8.2/mapbox-gl.js"></script>
    <style>
        body {
            margin: 0;
            padding: 0;
        }

        #map {
            position: absolute;
            top: 0;
            bottom: 0;
            width: 100%;
            height: 100%;
        }
    </style>
</head>

<body>


    <div id='map'></div>

    <script>
        mapboxgl.accessToken =
            'pk.eyJ1IjoibHh0aWFudGlhbiIsImEiOiJjaXd2ZjlkYnQwMTZvMnRtYWZnM2lpbHFvIn0.ef3rFZTr9psmLWahrqap2A';
        var map = new mapboxgl.Map({
            container: 'map',
            style: 'mapbox://styles/mapbox/light-v10',
            center: [-103.59179687498357, 40.66995747013945],
            zoom: 3
        });

        map.on('load', function () {
            // Add a new source from our GeoJSON data and set the
            // 'cluster' option to true. GL-JS will add the point_count property to your source data.
            // 添加数据源
            map.addSource("earthquakes", {
                type: "geojson",
                // Point to GeoJSON data. This example visualizes all M1.0+ earthquakes
                // from 12/22/15 to 1/21/16 as logged by USGS' Earthquake hazards program.
                data: "https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson",
                cluster: true,
                clusterMaxZoom: 14, // Max zoom to cluster points on
                clusterRadius: 50 // Radius of each cluster when clustering points (defaults to 50)
            });
            // 添加圆形聚合图层
            map.addLayer({
                id: "clusters",
                type: "circle",
                source: "earthquakes",
                filter: ["has", "point_count"],
                paint: {
                    // Use step expressions (https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions-step)
                    // with three steps to implement three types of circles:
                    //   * Blue, 20px circles when point count is less than 100
                    //   * Yellow, 30px circles when point count is between 100 and 750
                    //   * Pink, 40px circles when point count is greater than or equal to 750
                    "circle-color": [
                        "step",
                        ["get", "point_count"],
                        "#51bbd6",
                        100,
                        "#f1f075",
                        750,
                        "#f28cb1"
                    ],
                    "circle-radius": [
                        "step",
                        ["get", "point_count"],
                        20,
                        100,
                        30,
                        750,
                        40
                    ]
                }
            });
            // 添加数字图层
            map.addLayer({
                id: "cluster-count",
                type: "symbol",
                source: "earthquakes",
                filter: ["has", "point_count"],
                layout: {
                    "text-field": "{point_count_abbreviated}",
                    "text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Bold"],
                    "text-size": 12
                }
            });
            // 添加未聚合图层
            map.addLayer({
                id: "unclustered-point",
                type: "circle",
                source: "earthquakes",
                filter: ["!", ["has", "point_count"]],
                paint: {
                    "circle-color": "#11b4da",
                    "circle-radius": 4,
                    "circle-stroke-width": 1,
                    "circle-stroke-color": "#fff"
                }
            });

            // inspect a cluster on click  点击聚合图层地图级别中心点变化
            map.on('click', 'clusters', function (e) {
                var features = map.queryRenderedFeatures(e.point, {
                    layers: ['clusters']
                });
                console.log('features', features);
                var clusterId = features[0].properties.cluster_id;
                map.getSource('earthquakes').getClusterExpansionZoom(clusterId, function (err, zoom) {
                    if (err) return;

                    map.easeTo({
                        center: features[0].geometry.coordinates,
                        zoom: zoom
                    });
                });

                // 获取当前聚合点下一级子元素
                map.getSource('earthquakes').getClusterChildren(clusterId, (error, features) => {
                    if (!error) {
                        console.log('Cluster children:', features);
                    }
                });

                // 获取当前聚合点下边的所有子元素
                let allFeatures = [];
                const getFeatures = (id) => {
                    map.getSource('earthquakes').getClusterChildren(id, (error, features) => {
                        features.forEach(feature => {
                            const {id=''} = feature;
                            id && getFeatures(id);
                            !id && allFeatures.push(feature);
                            console.log('allFeatures', allFeatures);
                        });
                    });
                };
                
                getFeatures(clusterId);
            });
            // 聚合图层鼠标移入样式
            map.on('mouseenter', 'clusters', function (e) {
                console.log('cluster', e);
                map.getCanvas().style.cursor = 'pointer';
            });
            // 聚合图层鼠标移出鼠标样式
            map.on('mouseleave', 'clusters', function () {
                map.getCanvas().style.cursor = '';
            });
            let popup = new mapboxgl.Popup({
                className: 'my-class'
            });
            // 未聚合图层鼠标移入pop框显示
            map.on('mouseenter', 'unclustered-point', function (e) {
                console.log(e)
                // 改变鼠标样式
                map.getCanvas().style.cursor = 'pointer';
                let features = e.features[0].properties;
                popup.setLngLat(e.lngLat)
                popup.setHTML(`<h3>id: ${features.id}</h3><h3>time: ${features.time}</h3>`)
                popup.setMaxWidth("300px")
                popup.addTo(map);
            });
            // 未聚合图层鼠标移出pop框隐藏
            map.on('mouseleave', 'unclustered-point', function () {
                // 改变鼠标样式
                map.getCanvas().style.cursor = '';
                popup.remove();
            });
        });
    </script>

</body>

</html>

效果展示:

### 使用Mapbox GL JS 实现前端数据点聚合 #### 数据点聚合的概念 在地理信息系统(GIS)应用中,当大量位置标记被放置在同一区域时,为了提高可视化效果和用户体验,通常会采用一种称为“聚簇”的技术来减少视觉混乱并提升性能。通过这种方式,相近的数据点会被组合成单个集群图标展示给用户。 对于Mapbox GL JS而言,其内置支持基于超级圈(Supercluster)算法的数据点自动聚集功能[^1]。这使得开发者能够轻松处理大规模空间分布型数据集,在不同缩放级别下动态调整显示方式。 #### 如何启用数据点聚合 要实现在前端利用Mapbox GL JS完成数据点的聚合操作,主要涉及以下几个方面: - **引入必要的依赖项** 确保项目环境中已经包含了`mapbox-gl.js`以及官方推荐使用的聚类库——supercluster。如果是在Vue框架内集成,则还需考虑组件化封装等问题[^4]。 - **创建GeoJSON源** 准备待聚合的空间要素集合作为输入源,一般形式为FeatureCollection类型的GeoJSON对象。这些特征应至少包含坐标属性和其他描述性字段以便后续定制样式逻辑。 ```javascript const geojsonData = { "type": "FeatureCollection", "features": [ {"type": "Feature", "geometry": { "type": "Point", "coordinates": [-73.9808, 40.7648]}, properties: {}}, // 更多feature... ] }; ``` - **配置Cluster Layer** 向地图实例添加新的图层定义,指定该图层负责呈现经过聚合后的结果视图。注意设置合理的半径范围(`radius`)以控制相邻节点间的最小间距;同时允许自定义未分组状态下的基础符号外观(`circle-color`, `circle-radius`等)[^2]. ```javascript // 添加一个source到地图中,使用geojsonData作为初始数据,并开启clustering选项 map.addSource('earthquakes', { type: 'geojson', data: geojsonData, cluster: true, clusterMaxZoom: 14, // 超过此级别的zoom不会进行clustering clusterRadius: 50 // 影响points之间的距离 }); // 定义两个layers分别对应于单独point和平铺后的clusters map.addLayer({ id: 'unclustered-point', type: 'circle', source: 'earthquakes', filter: ['!', ['has', 'point_count']], // 过滤掉所有的clusters paint: { 'circle-color': '#11b4da', 'circle-radius': 6, 'circle-stroke-width': 1, 'circle-stroke-color': '#fff' } }); map.addLayer({ id: 'clusters', type: 'circle', source: 'earthquakes', filter: ['has', 'point_count'], paint: { 'circle-color': [ 'step', ['get', 'point_count'], '#fca2a2', 100, '#eaa2ac', 750, '#c87ba7' ], 'circle-radius': [ 'step', ['get', 'point_count'], 20, 100, 30, 750, 40 ] } }); ``` 上述代码片段展示了如何构建基本的地图布局结构,其中包括原始散列点与它们所形成的群集两种表现形态。随着用户的浏览行为改变(比如放大缩小),系统将会依据当前视野内的实际状况实时更新各元素的位置关系及其对应的渲染模式[^3]。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值