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

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 Openlayers中使用Cluster+Overlay实现点击单个要素和聚合要素时显示不同弹窗,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

场景

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

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

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

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

注:

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

实现

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

可以参考如下

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

Vue+Openlayer使用overlay实现弹窗弹出显示与关闭_BADAO_LIUMANG_QIZHI的博客-CSDN博客

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;
            width: 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 {
            width: 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;
            width: 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 {
            width: 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.bmabk.com/index.php/post/136133.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!