Openlayers中使用Overlay实现点击要素弹窗并且弹窗随之移动

摘要:
要实现的效果是单击要弹出的元素,弹出窗口将随着元素的移动而移动。实施1。实现弹出窗口的代码与上面的代码基本相同。不同之处在于,添加了一个布尔变量来控制是否显示弹出窗口变量ShowDialog=false;let_ that=此;map.on;布尔变量的默认值为false。在地图的单击事件中,捕获元素后,将其设置为true。
场景

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

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

实现弹窗的效果可以参考上面。

要实现的效果是点击某个元素弹窗显示,并且弹窗随着元素的移动而移动。

实现元素移动的效果可以参考如下:

Openlayers中使用Image的rotation实现车辆定位导航带转角(判断车辆图片旋转角度):

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

结合以上两个的效果

Openlayers中使用Overlay实现点击要素弹窗并且弹窗随之移动第1张

注:

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

实现

1、实现弹窗的代码基本同上,不同的是添加了一个布尔变量,控制是否显示弹窗

        var isShowDialog = false;
        let _that = this;
        map.on('singleclick', function (evt) {
            let coordinate = evt.coordinate
            // 点击尺 (这里是尺(米),并不是经纬度);
            var feature = map.forEachFeatureAtPixel(evt.pixel, (feature) => {
                return feature;
            });
            if (feature) { //捕捉到要素
                content.innerHTML = `
                    <p>公众号:</p>
                    <p>霸道的程序猿</p>`;
                _that.overlay.setPosition(coordinate); //把 overlay 显示到指定的 x,y坐标
                isShowDialog = true;
            } else {
                console.log("没有元素");
            }
        });

布尔变量的默认值为false,在地图的点击事件中,捕获到元素之后,将其设置为true。

2、然后定时器一直监测

            setTimeout(() => {
                if (isShowDialog) {
                    this.overlay.setPosition([Number(item.x), Number(item.y)]);
                }
            }, 0);

当布尔变量为true时,将overlay弹窗显示在当前坐标位置上。

这里的item.x是通过定时器模拟获取的后台坐标数据。

3、在弹窗的关闭事件中再将布尔变量设置为false

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

4、完整示例代码

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

<head>
    <meta charset="UTF-8">
    <title>OpenLayers example</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 wrnameData = [{
                x: '-11561016.25956459',
                y: '5542204.803284118',
                wrname: '公众号'
            },
            {
                x: '-11562479.441174088',
                y: '5540478.999423137',
                wrname: '霸道的程序猿'
            }
        ];

        //定位数据源
        var positionData = [{
                x: '-11560139.941628069',
                y: '5538515.7834814',
                carNumber: '霸道的程序猿'
            },
            {
                x: '-11560039.941628069',
                y: '5537515.7834814',
                carNumber: '霸道的程序猿'
            },
            {
                x: '-11559039.941628069',
                y: '5536515.7834814',
                carNumber: '霸道的程序猿'
            },
            {
                x: '-11558039.941628069',
                y: '5535515.7834814',
                carNumber: '霸道的程序猿'
            },
            {
                x: '-11557039.941628069',
                y: '5534515.7834814',
                carNumber: '霸道的程序猿'
            },
            {
                x: '-11556039.941628069',
                y: '5533515.7834814',
                carNumber: '霸道的程序猿'
            },
            {
                x: '-11555039.941628069',
                y: '5532515.7834814',
                carNumber: '霸道的程序猿'
            },
            {
                x: '-11554039.941628069',
                y: '5531515.7834814',
                carNumber: '霸道的程序猿'
            },
            {
                x: '-11553039.941628069',
                y: '5530515.7834814',
                carNumber: '霸道的程序猿'
            },
            {
                x: '-11552039.941628069',
                y: '5529515.7834814',
                carNumber: '霸道的程序猿'
            },
            {
                x: '-11551039.941628069',
                y: '5528515.7834814',
                carNumber: '霸道的程序猿'
            },
            {
                x: '-11550039.941628069',
                y: '5527515.7834814',
                carNumber: '霸道的程序猿'
            },
            {
                x: '-11549039.941628069',
                y: '5526515.7834814',
                carNumber: '霸道的程序猿'
            },
            {
                x: '-11548039.941628069',
                y: '5525515.7834814',
                carNumber: '霸道的程序猿'
            },
            {
                x: '-11547039.941628069',
                y: '5524515.7834814',
                carNumber: '霸道的程序猿'
            },
            {
                x: '-11546039.941628069',
                y: '5523515.7834814',
                carNumber: '霸道的程序猿'
            }

        ];

        // 打点图标的图层
        var pointLayer = new ol.layer.Vector({
            source: new ol.source.Vector({
                features: []
            })
        })

        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 drwaSource = new ol.source.Vector({
            wrapX: false
        })

        //线的图层
        var lineVector = new ol.layer.Vector({
            source: self.drwaSource
        });


        //定位图层的Source
        var positonSource = new ol.source.Vector({
            features: []
        });

        // 定位图层
        var positionLayer = new ol.layer.Vector({
            source: positonSource
        });

        //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, pointLayer, lineVector, positionLayer],
            target: 'map',
            view: view
        });

        //单击获取地图坐标
        map.on('singleclick', (evt) => {
            console.log(evt.coordinate);
        });

        //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);
        }

        //调用画线方法
        this.drawLine();

        /**
         * 画线
         * */
        function drawLine() {
            let self = this
            //设置起点与终点
            let pointData = [
                [-11561569.727802912, 5540797.727555227],
                [-11563653.520735113, 5540037.346516268]
            ]
            //下边来添加一线feature
            var feature = new ol.Feature({
                type: 'lineStyle',
                geometry: new ol.geom.LineString(
                    pointData // 线的坐标
                )
            })
            //设置线的样式
            let lineStyle = new ol.style.Style({
                stroke: new ol.style.Stroke({
                    color: 'red',
                     4
                })
            })
            // 添加线的样式
            feature.setStyle(lineStyle)
            // 添加线的fature
            self.drwaSource.addFeature(feature)
        }

        //清除线的方法
        function clearLine() {
            this.drwaSource.clear();
        }
        // 获取到弹框的节点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();
            isShowDialog = false;
            return false;
        };
        // 创建一个弹窗 Overlay 对象
        var overlay = new ol.Overlay({
            element: container, //绑定 Overlay 对象和 DOM 对象的
            autoPan: true, // 定义弹出窗口在边缘点击时候可能不完整 设置自动平移效果
            autoPanAnimation: {
                duration: 250 //自动平移效果的动画时间 9毫秒
            }
        });
        map.addOverlay(overlay);
        //控制是否显示弹窗
        var isShowDialog = false;
        let _that = this;
        map.on('singleclick', function (evt) {
            let coordinate = evt.coordinate
            // 点击尺 (这里是尺(米),并不是经纬度);
            var feature = map.forEachFeatureAtPixel(evt.pixel, (feature) => {
                return feature;
            });
            if (feature) { //捕捉到要素
                content.innerHTML = `
                    <p>公众号:</p>
                    <p>霸道的程序猿</p>`;
                _that.overlay.setPosition(coordinate); //把 overlay 显示到指定的 x,y坐标
                isShowDialog = true;
            } else {
                console.log("没有元素");
            }
        });

        //调用打点方法
        this.drawPoint();
        /**
         * 图标文字打点
         * */
        function drawPoint() {
            this.wrnameData.forEach((item, index) => {
                var feature = new ol.Feature({
                    geometry: new ol.geom.Point([Number(item.x), Number(item.y)])
                })
                let style = 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: `${item.wrname}`,
                    })
                })
                feature.setStyle(style);
                this.pointLayer.getSource().addFeature(feature);
            });
        }

        //定时器循环模拟定位效果
        var index = 0;
        setInterval(() => {
            //坐标数据到头了 就重新开始
            if (index > this.positionData.length - 2) {
                index = 0;
            }

            //定义角度
            var rotation = 0;
            //如果是最后一个点
            if (index == this.positionData.length - 1) {
                rotation = setAngle(this.positionData[index], this.positionData[index]);
            } else {
                rotation = setAngle(this.positionData[index], this.positionData[index + 1]);
            }

            //根据索引获取数据
            var item = this.positionData[index];
            //清除上次的
            if (this.positonSource) {
                this.positonSource.clear();
            }
            var feature = new ol.Feature({
                geometry: new ol.geom.Point([Number(item.x), Number(item.y)])
            });

            var style = new ol.style.Style({
                image: new ol.style.Icon({
                    scale: 0.8,
                    src: './icon/car.png',
                    anchor: [0.48, 0.52],
                    //设置旋转角度
                    rotation: -rotation,
                }),
                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: `${item.carNumber}`,
                })
            });

            //设置样式
            feature.setStyle(style);
            //添加feture
            this.positonSource.addFeature(feature)
            setTimeout(() => {
                if (isShowDialog) {
                    this.overlay.setPosition([Number(item.x), Number(item.y)]);
                }
            }, 0);
            //移到下个点
            index++;
        }, 1000);

        // 点位转角
        function setAngle(first, second) {
            var dx = second.x - first.x
            var dy = second.y - first.y
            var rotation = Math.atan2(dy, dx)
            return rotation
        }
    </script>

</body>

</html>

免责声明:文章转载自《Openlayers中使用Overlay实现点击要素弹窗并且弹窗随之移动》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇免疫信息学C#调用WPS将文档转换成pdf进行预览下篇

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

相关文章

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

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

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

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

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

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

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

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

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

场景 Openlayers中使用Cluster实现缩放地图时图层聚合与取消聚合: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/122143275 上面实现缩放地图时元素在指定距离内实现聚合效果。 实际场景中点位是变化的,不是静态的点位,当多个点位在动态更新的过程中如果出现了重合则自动...

openlayers 加载瓦片详解 一

在这先说点题外话,本人在研究webgl三维球过程中惊人发现,openlayers 的开发人员也在研究webgl并经证实他们也正在研发基于 webgl的三维gis开源平台,这可能是首个开源的三维平台,在现在三维大趋势下,看来openlayers 前景还是一片大好,闲话少说,静候佳音。 在这将分4篇文章来系统的详细的介绍openlayers 是怎么来加载本地及...