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

摘要:
事实上,它是为了取代原来的普通newol。来源矢量层数据源。来源Cluster4,并创建一个新的聚合层varclusterLayer=newol。层矢量;事实上,实现聚合和非聚合效果的关键代码是将此部分的样式更改为根据条件动态运行和返回。
场景

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

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/122143275

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

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

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

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

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

实现

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中实现地图上打点并显示图标和文字:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/118631046

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;
             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>

免责声明:文章转载自《Openlayers中使用Cluster实现点位元素重合时动态聚合与取消聚合》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇未安装git lfs导致git下载不完整,没有错误提示在WIn10上删除以windows保留字命名的文件下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

编程王道,唯“慢”不破

原文地址 人和人之间编程速度的差异还是很大的,有的程序猿写代码非常快,有的却常常是龟速。Jeffrey Ventrella 最近在一篇文章里探讨了这种编程速度的差异,他是绝对的龟速派代表,来看看他对编程速度的看法: 我爸常跟我说的一句话是,慢一点码,才能快点把程序写完。 我在旧金山很多家互联网公司工作过,现在已经 52 岁了,对于程序猿这个职业来说,我的年...

漫谈怎样学习操作系统原理

       本人学习计算机技术至今,对于怎样学习操作系统原理有一点自己的看法,如今写出来,希望对大家能有所助!        操作系统怎么学。首先要想操作系统是怎么来的,在没有操作系统的年代里,人们是怎么编程的。 这是首要的问 题。不知道有没有人看过INTEL官方的CPU文档,总是分为应用级编程、系统级编程、指令集这三块。当中系统级编 程这一块最复...

(转)Openlayers 2.X加载天地图

http://blog.csdn.net/gisshixisheng/article/details/44621923 概述: 在前面的章节,讲到了Arcgis for js加载天地图,在本节讲述如何在Openlayers 2.X的版本中加载天地图,并添加自己的wms服务。 效果: 地图 影像 地形 去掉本地wms 实现: 1、天地图服务 在天地图...

JavaScript基础知识总结

声明:本文摘抄自:https://blog.csdn.net/qq_39043923/article/details/89204263 JavaScript基础 浏览器说明 浏览器是指可以显示网页服务器或者文件系统的HTML文件内容,并让用户与这些文件交互的一种软件。 通俗的讲:可以显示页面的一个软件, 国内网民计算机上常见的网页浏览器有,QQ浏览器、In...

重写 geturl Openlayers中使用TileCache加载预切割图片作为基础地图图层

Openlayers中使用TileCache加载预切割图片作为基础地图图层 博客分类:OpenLayers prototype算法 Openlayers使用TileCache对象加载预切割的图片。每张图片一张瓦片;其中的getURL(bound)返回的就是我们需要实现的图片地址;所以实现图片地址计算算法在该函数实现;参数bound就是一张图...

今年美国什么工作最吃香?程序猿薪酬超医生

[导读]美国程序猿平均年薪90060美元,成美国今年最佳职业。被人们普遍看好的医生职业仅名列第八。 USNews最新发布了2014年全美最佳职业TOP100排行榜(The 100 Best Jobs)。当中软件开发员名列该榜单榜首,计算机系统分析师位列第2,而第3名则是牙医。 依据美国劳工部门提供的最新数据显示,软件开发者(...