Openlayers中使用Cluster实现点位元素重合时动态聚合与取消聚合

场景

Openlayers中使用Cluster实现缩放地图时图层聚合与取消聚合:

Openlayers中使用Cluster实现缩放地图时图层聚合与取消聚合_BADAO_LIUMANG_QIZHI的博客-CSDN博客

上面实现缩放地图时元素在指定距离内实现聚合效果。 

实际场景中点位是变化的,不是静态的点位,当多个点位在动态更新的过程中如果出现了重合则自动实现聚合效果

注:

博客:
BADAO_LIUMANG_QIZHI的博客_霸道流氓气质_CSDN博客-C#,SpringBoot,架构之路领域博主
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

实现

1、首先模拟多个点位坐标的数据,实际场景可能是从后台或其他地方获取点位信息

        //定位数据源
        var positionData = [
            [{
                    x: '-11561139.941628069',
                    y: '5538515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11552039.941628069',
                    y: '5531515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11560039.941628069',
                    y: '5537515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11553039.941628069',
                    y: '5536515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11559039.941628069',
                    y: '5536515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11554039.941628069',
                    y: '5536515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11558039.941628069',
                    y: '5535515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11557039.941628069',
                    y: '5534515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11557039.941628069',
                    y: '5534515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11556039.941628069',
                    y: '5535515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11556039.941628069',
                    y: '5533515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11557039.941628069',
                    y: '5536515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11555039.941628069',
                    y: '5533515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11558039.941628069',
                    y: '5536515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11554039.941628069',
                    y: '5533515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11559039.941628069',
                    y: '5536515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11553039.941628069',
                    y: '5533515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11560039.941628069',
                    y: '5536515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11552039.941628069',
                    y: '5533515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11561039.941628069',
                    y: '5536515.7834814',
                    carNumber: '公众号'
                }
            ]
        ];

这里模拟两组坐标的点位数据,会在中间某个时刻有距离特别相近的点位。

2、创建聚合图层要素

        // 创建聚合图层要素
        var clusterSource = new ol.source.Vector();

3、新建聚合图层数据源

        // 聚合图层数据源
        var clusterSourceForLayer = new ol.source.Cluster({
            source: clusterSource,
            distance: 50
        })

这里的distance就是指的聚合的距离。

实际上就是将原来的普通的new ol.source.Vector图层数据源更换为ol.source.Cluster

4、新建聚合图层

        var clusterLayer = new ol.layer.Vector({
            source: clusterSourceForLayer,
            style: function (feature, resolution) {
                var size = feature.get('features').length;
                if (size == 1) {
                    return new ol.style.Style({
                        image: new ol.style.Icon({
                            scale: 0.8,
                            src: './icon/house.png',
                            anchor: [0.48, 0.52]
                        }),
                        text: new ol.style.Text({
                            font: 'normal 12px 黑体',
                            // // 对其方式
                            textAlign: 'center',
                            // 基准线
                            textBaseline: 'middle',
                            offsetY: -35,
                            offsetX: 0,
                            backgroundFill: new ol.style.Stroke({
                                color: 'rgba(0,0,255,0.7)',
                            }),
                            // 文本填充样式
                            fill: new ol.style.Fill({
                                color: 'rgba(236,218,20,1)'
                            }),
                            padding: [5, 5, 5, 5],
                            text: `霸道的程序猿`,
                        })
                    });
                } else {
                    return new ol.style.Style({
                        image: new ol.style.Circle({
                            radius: 30,
                            stroke: new ol.style.Stroke({
                                color: 'white'
                            }),
                            fill: new ol.style.Fill({
                                color: 'blue'
                            })
                        }),
                        text: new ol.style.Text({
                            text: size.toString(),
                            fill: new ol.style.Fill({
                                color: 'white'
                            })
                        })
                    });
                }
            }
        });

实际上实现聚合与不聚合效果的关键代码就是这部分的style改为函数并且根据条件动态返回。

如果包含多个元素,则返回聚合的style效果,否则就是返回普通的style效果。

5、map上添加图层

        var map = new ol.Map({
            layers: [layer],
            target: 'map',
            view: view
        });

         this.map.addLayer(this.clusterLayer);

其中layer是地图图层。

然后新建一个定时器模拟定时获取点位数据

        //定时器循环模拟后台获取数据实现定位效果
        var index = 0;
        setInterval(() => {
            //坐标数据到头了 就重新开始
            if (index > this.positionData.length - 2) {
                index = 0;
            }
            //根据索引获取数据
            var item = this.positionData[index];
            //清除上次的数据源
            if (this.positonSource) {
                this.positonSource.clear();
            }
            if (item) {
                clusterSource.clear();
                for (var i = 0; i < item.length; ++i) {
                    var feature = new ol.Feature({
                        geometry: new ol.geom.Point([Number(item[i].x), Number(item[i].y)])
                    })
                    //数据源添加要素
                    clusterSource.addFeature(feature);
                }
            }   
            //移到下个点
            index++;
        }, 1000);

在定时器中将聚合图层的数据源先清理,然后再将坐标要素添加进聚合图层数据源中。

其他相关代码就是离线加载地图显示的功能,可以参考

Openlayers中实现地图上打点并显示图标和文字:

Openlayers中实现地图上打点并显示图标和文字_BADAO_LIUMANG_QIZHI的博客-CSDN博客_openlayers 打点

6、完整示例代码

<!doctype html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>缩放地图实现聚合与取消聚合-动态</title>
    <link rel="stylesheet" href="lib/ol65/ol.css" type="text/css">
    <style>
        html,
        body,
        #map {
            padding: 0;
            margin: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }
    </style>
</head>

<body>
    <div id="map"></div>
    <script type="text/javascript" src="lib/ol65/ol.js"></script>
    <script type="text/javascript">
        //定位数据源
        var positionData = [
            [{
                    x: '-11561139.941628069',
                    y: '5538515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11552039.941628069',
                    y: '5531515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11560039.941628069',
                    y: '5537515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11553039.941628069',
                    y: '5536515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11559039.941628069',
                    y: '5536515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11554039.941628069',
                    y: '5536515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11558039.941628069',
                    y: '5535515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11557039.941628069',
                    y: '5534515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11557039.941628069',
                    y: '5534515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11556039.941628069',
                    y: '5535515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11556039.941628069',
                    y: '5533515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11557039.941628069',
                    y: '5536515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11555039.941628069',
                    y: '5533515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11558039.941628069',
                    y: '5536515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11554039.941628069',
                    y: '5533515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11559039.941628069',
                    y: '5536515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11553039.941628069',
                    y: '5533515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11560039.941628069',
                    y: '5536515.7834814',
                    carNumber: '公众号'
                }
            ],
            [{
                    x: '-11552039.941628069',
                    y: '5533515.7834814',
                    carNumber: '霸道的程序猿'
                },
                {
                    x: '-11561039.941628069',
                    y: '5536515.7834814',
                    carNumber: '公众号'
                }
            ]
        ];

        var source = new ol.source.XYZ({
            tileUrlFunction: function (xyz, obj1, obj2) {
                if (!xyz)
                    return "";
                var z = xyz[0];
                var x = Math.abs(xyz[1]);
                var y = Math.abs(xyz[2]);
                var xyz_convert = self.convert_(z, x, y);
                x = xyz_convert[0];
                y = xyz_convert[1];
                z = xyz_convert[2];
                var shift = z / 2;
                var half = 2 << shift;
                var digits = 1;
                if (half > 10)
                    digits = parseInt(Math.log(half) / Math.log(10)) + 1;
                var halfx = parseInt(x / half);
                var halfy = parseInt(y / half);
                x = parseInt(x);
                y = parseInt(y) - 1;
                var url = "./images/EPSG_900913" + "_" + self.padLeft_(2, z) + "/" + self.padLeft_(digits,
                        halfx) + "_" + self.padLeft_(digits, halfy) + "/" + self.padLeft_(2 * digits, x) +
                    "_" + self.padLeft_(2 * digits, y) + "." + 'png';
                return url;
            }
        });

        //projections投影坐标系转换相关的操作
        var projection = new ol.proj.Projection({
            code: 'EPSG:900913',
            units: 'm',
            axisOrientation: 'neu'
        });

        //Layers 图层管理类,用来管理图层信息。主要包括Tile,Image,Vector,VectorTile等图层。
        var layer = new ol.layer.Tile({
            source: source
        });

        // 创建聚合图层要素
        var clusterSource = new ol.source.Vector();

        // 聚合图层数据源
        var clusterSourceForLayer = new ol.source.Cluster({
            source: clusterSource,
            distance: 50
        })

        // 聚合图层
        var clusterLayer = new ol.layer.Vector({
            source: clusterSourceForLayer,
            style: function (feature, resolution) {
                var size = feature.get('features').length;
                if (size == 1) {
                    return new ol.style.Style({
                        image: new ol.style.Icon({
                            scale: 0.8,
                            src: './icon/house.png',
                            anchor: [0.48, 0.52]
                        }),
                        text: new ol.style.Text({
                            font: 'normal 12px 黑体',
                            // // 对其方式
                            textAlign: 'center',
                            // 基准线
                            textBaseline: 'middle',
                            offsetY: -35,
                            offsetX: 0,
                            backgroundFill: new ol.style.Stroke({
                                color: 'rgba(0,0,255,0.7)',
                            }),
                            // 文本填充样式
                            fill: new ol.style.Fill({
                                color: 'rgba(236,218,20,1)'
                            }),
                            padding: [5, 5, 5, 5],
                            text: `霸道的程序猿`,
                        })
                    });
                } else {
                    return new ol.style.Style({
                        image: new ol.style.Circle({
                            radius: 30,
                            stroke: new ol.style.Stroke({
                                color: 'white'
                            }),
                            fill: new ol.style.Fill({
                                color: 'blue'
                            })
                        }),
                        text: new ol.style.Text({
                            text: size.toString(),
                            fill: new ol.style.Fill({
                                color: 'white'
                            })
                        })
                    });
                }
            }
        });

        //View 视图管理器,主要用来管理地图视图,分辨率或旋转,中心、投影、分辨率、缩放级别等。
        var view = new ol.View({
            //中心点
            center: [-11549894, 5533433],
            //缩放等级
            zoom: 11,
            //投影坐标系
            projection: projection,
            //边界
            extent: [-20037508.34, -20037508.34, 20037508.34, 20037508.34]
        });

        //Map Openlayers的核心组件,包含图层、交互事件、UI控制元素等。
        var map = new ol.Map({
            layers: [layer],
            target: 'map',
            view: view
        });

         this.map.addLayer(this.clusterLayer);

        //定时器循环模拟后台获取数据实现定位效果
        var index = 0;
        setInterval(() => {
            //坐标数据到头了 就重新开始
            if (index > this.positionData.length - 2) {
                index = 0;
            }
            //根据索引获取数据
            var item = this.positionData[index];
            //清除上次的数据源
            if (this.positonSource) {
                this.positonSource.clear();
            }
            if (item) {
                clusterSource.clear();
                for (var i = 0; i < item.length; ++i) {
                    var feature = new ol.Feature({
                        geometry: new ol.geom.Point([Number(item[i].x), Number(item[i].y)])
                    })
                    //数据源添加要素
                    clusterSource.addFeature(feature);
                }
            }   
            //移到下个点
            index++;
        }, 1000);


        //xy行列转换
        function convert_(zoomLevel, x, y) {
            var extent = Math.pow(2, zoomLevel);
            if (x < 0 || x > extent - 1) {
                console.log("The X coordinate is not sane: " + x);
                return;
            }
            if (y < 0 || y > extent - 1) {
                console.log("The Y coordinate is not sane: " + y);
                return;
            }
            // openlayers 6.0版本
            var gridLoc = [x, extent - y, zoomLevel];

            // openlayers 4.5版本
            // var gridLoc = [x, extent - y + 1, zoomLevel];
            return gridLoc;
        }

        //字符截取
        function padLeft_(num, val) {
            return (new Array(num).join('0') + val).slice(-num);
        }
    </script>
</body>

</html>

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
实现在 Vue 使用 OpenLayers 实现聚合点位击事件,可以按照以下步骤进行: 1. 在 Vue 安装 OpenLayers:可以使用命令 `npm install ol` 安装 OpenLayers。 2. 在 Vue 创建地图容器:可以在 Vue 的 `template` 创建一个 `div` 容器作为地图容器。 3. 在 Vue 使用 OpenLayers 创建地图:可以在 Vue 的 `methods` 创建一个函数,使用 OpenLayers 创建地图。 4. 在地图添加聚合点位图层:在创建地图的过程,可以添加一个聚合点位图层。 5. 监听聚合点位图层的击事件:可以在创建地图的过程使用 OpenLayers 提供的 `on` 方法监听聚合点位图层的击事件。 6. 在击事件获取聚合点位的信息:在监听到聚合点位图层的击事件后,可以获取聚合点位的信息并进行相应处理。 以下是一个基本的 Vue 组件代码示例,用于实现 OpenLayers 聚合点位击事件: ```html <template> <div id="map"></div> </template> <script> import 'ol/ol.css'; import { Map, View } from 'ol'; import { fromLonLat } from 'ol/proj'; import { Cluster, OSM, Vector } from 'ol/source'; import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer'; import Feature from 'ol/Feature'; import Point from 'ol/geom/Point'; export default { name: 'Map', mounted() { this.initMap(); }, methods: { initMap() { const source = new Cluster({ distance: 40, source: new Vector({ url: 'data/kml/2012_Earthquakes_Mag5.kml', format: new KML({ extractStyles: false, }), }), }); const clusterLayer = new VectorLayer({ source: source, }); const map = new Map({ target: 'map', layers: [ new TileLayer({ source: new OSM(), }), clusterLayer, ], view: new View({ center: fromLonLat([-117.1497, 32.6965]), zoom: 12, }), }); clusterLayer.getSource().on('addfeature', function (event) { const cluster = event.feature; if (cluster.get('features').length > 1) { const coordinates = cluster.getGeometry().getCoordinates(); const feature = new Feature(new Point(coordinates)); feature.set('cluster', cluster); source.addFeature(feature); } }); clusterLayer.getSource().on('click', function (event) { const feature = map.forEachFeatureAtPixel(event.pixel, function (feature) { return feature; }); if (feature && feature.get('cluster')) { const cluster = feature.get('cluster'); const features = cluster.get('features'); const coordinate = cluster.getGeometry().getCoordinates(); console.log(features); console.log(coordinate); } }); }, }, }; </script> <style> #map { height: 400px; } </style> ``` 在上述代码示例,我们使用 OpenLayers 创建了一个聚合点位图层,并在地图添加了该图层。然后,我们使用 `on` 方法来监听聚合点位图层的击事件,并在击事件获取聚合点位的信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霸道流氓气质

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值