• Openlayers中使用Cluster+Overlay实现点击单个要素和聚合要素时显示不同弹窗


    场景

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

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

    在上面实现聚合效果之后,如果要实现点击聚合要素与单个要素时弹出不同的弹窗。

     注:

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

    实现

    1、首先实现点击要素弹窗的实现

    可以参考如下

    Vue+Openlayer使用overlay实现弹窗弹出显示与关闭:

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

    2、关键就是监听地图的单击事件并根据要素的个数分别弹窗显示不同的内容

            map.on('singleclick', function (evt) {
                if (feature) { //捕捉到要素
                    if (feature.values_.features && feature.values_.features.length == 1) { //只有一个要素
                        console.log("进入单元素聚合");
                    } else { //有多个要素                                                  
                        console.log("有多个要素");
                    }
                } else {
                    console.log("没有元素");
                }
            });

    3、添加弹窗的标签

        <div id="popup" class="ol-popup">
            <a href="#" id="popup-closer" class="ol-popup-closer">X</a>
            <div id="popup-content" class="popup-content"></div>
        </div>

    4、设置窗体的样式

        <style>
            html,
            body,
            #map {
                padding: 0;
                margin: 0;
                 100%;
                height: 100%;
                overflow: hidden;
            }
    
            .ol-popup {
                position: absolute;
                background-color: white;
                -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
                filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
                padding: 15px;
                border-radius: 10px;
                border: 1px solid #cccccc;
                bottom: 12px;
                left: -50px;
            }
    
            .popup-content {
                 400px;
            }
    
            .ol-popup-closer {
                text-decoration: none;
                position: absolute;
                top: 2px;
                right: 8px;
            }
        </style>

    5、获取到弹窗的节点DOM

            // 获取到弹框的节点DOM
            var container = document.getElementById("popup");
            var content = document.getElementById("popup-content");
            var closer = document.getElementById("popup-closer");

    6、弹窗关闭事件

            //弹窗关闭事件
            closer.onclick = function () {
                _that.overlay.setPosition(undefined);
                closer.blur();
                return false;
            };

    7、创建overlay对象并添加到地图

            // 创建一个弹窗 Overlay 对象
            var overlay = new ol.Overlay({
                element: container, //绑定 Overlay 对象和 DOM 对象的
                autoPan: true, // 定义弹出窗口在边缘点击时候可能不完整 设置自动平移效果
                autoPanAnimation: {
                    duration: 250 //自动平移效果的动画时间 9毫秒
                }
            });
            map.addOverlay(overlay);

    8、其他都是加载离线瓦片地图的代码,完整示例代码

    <!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;
            }
    
            .ol-popup {
                position: absolute;
                background-color: white;
                -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
                filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
                padding: 15px;
                border-radius: 10px;
                border: 1px solid #cccccc;
                bottom: 12px;
                left: -50px;
            }
    
            .popup-content {
                 400px;
            }
    
            .ol-popup-closer {
                text-decoration: none;
                position: absolute;
                top: 2px;
                right: 8px;
            }
        </style>
    </head>
    
    <body>
        <div id="map"></div>
        <div id="popup" class="ol-popup">
            <a href="#" id="popup-closer" class="ol-popup-closer">X</a>
            <div id="popup-content" class="popup-content"></div>
        </div>
        <script type="text/javascript" src="lib/ol65/ol.js"></script>
        <script type="text/javascript">
            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();
            for (var i = 1; i <= 10; i++) {
                var coordinates = [-11551949.709486058 + Math.random(), 5533080.7247905275 + Math.random()];
                var feature = new ol.Feature(new ol.geom.Point(coordinates));
                clusterSource.addFeature(feature);
            }
            for (var i = 1; i <= 20; i++) {
                var coordinates = [-11553949.709486058 + Math.random(), 5527080.7247905275 + Math.random()];
                var feature = new ol.Feature(new ol.geom.Point(coordinates));
                clusterSource.addFeature(feature);
            }
    
            // 聚合图层数据源
            var clusterSourceForLayer = new ol.source.Cluster({
                source: clusterSource,
                distance: 100
            })
            // 聚合图层
            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, clusterLayer],
                target: 'map',
                view: view
            });
    
            // 获取到弹框的节点DOM
            var container = document.getElementById("popup");
            var content = document.getElementById("popup-content");
            var closer = document.getElementById("popup-closer");
            //弹窗关闭事件
            closer.onclick = function () {
                _that.overlay.setPosition(undefined);
                closer.blur();
                return false;
            };
            // 创建一个弹窗 Overlay 对象
            var overlay = new ol.Overlay({
                element: container, //绑定 Overlay 对象和 DOM 对象的
                autoPan: true, // 定义弹出窗口在边缘点击时候可能不完整 设置自动平移效果
                autoPanAnimation: {
                    duration: 250 //自动平移效果的动画时间 9毫秒
                }
            });
            map.addOverlay(overlay);
    
            let _that = this;
            map.on('singleclick', function (evt) {
                let coordinate = evt.coordinate
                // 点击尺 (这里是尺(米),并不是经纬度);
                var feature = map.forEachFeatureAtPixel(evt.pixel, (feature) => {
                    return feature;
                });
                if (feature) { //捕捉到要素
                    if (feature.values_.features && feature.values_.features.length == 1) { //只有一个要素
                        content.innerHTML = `
                        <p>只有一个要素的弹窗:</p>
                        <p>坐标:</p>X:${coordinate[0]} &nbsp;&nbsp; Y: ${coordinate[1]}`;
                        _that.overlay.setPosition(coordinate); //把 overlay 显示到指定的 x,y坐标
                        console.log("进入单元素聚合");
                    } else { //有多个要素                                                  
                        content.innerHTML = `
                        <p>有多个要素的弹窗:</p>
                        <p>坐标:</p>X:${coordinate[0]} &nbsp;&nbsp; Y: ${coordinate[1]}`;
                        _that.overlay.setPosition(coordinate); //把 overlay 显示到指定的 x,y坐标
                        console.log("有多个要素");
                    }
                } else {
                    console.log("没有元素");
                }
            });
            //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>
    博客园: https://www.cnblogs.com/badaoliumangqizhi/ 关注公众号 霸道的程序猿 获取编程相关电子书、教程推送与免费下载。
  • 相关阅读:
    ADO连接access和oracle的一个区别
    我的大救星——Oracle APEX 快速Web开发(鼠标点点即可开发出专业级Web应用)
    Sql Server 2008 R2 error:40 错误处理
    我的第一个WPF程序
    开源社会网络分析工具NodeXL介绍
    JavaScript学习笔记1之基础知识点
    JavaScript学习笔记6 之经典神坑题整理
    JavaScript学习笔记2之Tab切换
    变量声明和函数声明会提升到当前作用域顶部
    JavaScript学习笔记5 之 计时器 & scroll、offset、client系列属性 & 图片无缝滚动
  • 原文地址:https://www.cnblogs.com/badaoliumangqizhi/p/15739705.html
Copyright © 2020-2023  润新知