zoukankan      html  css  js  c++  java
  • Openlayers中使用Overlay实现点击要素弹窗并且弹窗随之移动

    场景

    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

    结合以上两个的效果

    注:

    博客:
    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>

    博客园: https://www.cnblogs.com/badaoliumangqizhi/ 关注公众号 霸道的程序猿 获取编程相关电子书、教程推送与免费下载。
  • 相关阅读:
    Linux学习笔记:【004】Linux内核代码风格
    ARM寄存器介绍
    2013 HTML5中国峰会演讲:Android上的HTML5:过去,现在和将来
    Ubuntu下编译SHTOOLS
    反对网抄,没有规则可以创建目标"install" 靠谱解答
    使用MTL库求解最小二乘解
    反对抄袭 正解spring的@Autowired 不要相信网上的错误版本
    浅析GDAL库C#版本支持中文路径问题(续)
    浅析GDAL库C#版本支持中文路径问题
    GDAL库调试(包括跨语言调试)
  • 原文地址:https://www.cnblogs.com/badaoliumangqizhi/p/15742637.html
Copyright © 2011-2022 走看看