zoukankan      html  css  js  c++  java
  • Vue+Openlayer使用overlay实现弹窗弹出显示与关闭

    场景

    Vue+Openlayers实现地图上绘制线:

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

    在上面的基础上实现点击地图,弹窗显示并获取点击处的坐标,并实现坐标转换经纬度。

    效果

    加载显示地图的流程

    Vue中使用Openlayers加载Geoserver发布的TileWMS:

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

    注:

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

    实现

    1、页面上添加弹窗的元素

    <template>
        <div id="app">
          <div id="map" class="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>
        </div>
    </template>

    2、添加弹窗样式

    <style scoped>
    .map {
       100%;
      height: 800px;
    }
    .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>

    3、导入相关模块

    //导入基本模块
    import "ol/ol.css";
    import Map from "ol/Map";
    import Overlay from "ol/Overlay";
    import View from "ol/View";
    import { Point,LineString } from "ol/geom";
    import Feature from "ol/Feature";
    import { Icon,Style,Stroke} from "ol/style";
    //导入相关模块
    import { Tile as TileLayer , Vector as VectorLayer } from 'ol/layer'
    import { TileWMS ,Vector as VectorSource } from 'ol/source'
    import { toStringHDMS } from "ol/coordinate";
    import { toLonLat } from "ol/proj";

    4、声明overlay与容器

          overlay: null,
          container: null, // 弹框

    5、在mounted中调用初始化地图的方法

      mounted() {
        this.initMap();
      },

    在方法中获取到弹窗的节点DOM

          // 获取到弹框的节点DOM
          var container = document.getElementById("popup");
          var content = document.getElementById("popup-content");
          var closer = document.getElementById("popup-closer");
    
    然后创建一个弹窗Overlay对象
    
          // 创建一个弹窗 Overlay 对象
          this.overlay = new Overlay({
              element: container, //绑定 Overlay 对象和 DOM 对象的
              autoPan: true, // 定义弹出窗口在边缘点击时候可能不完整 设置自动平移效果
              autoPanAnimation: {
                  duration: 250 //自动平移效果的动画时间 9毫秒
              }
          });

    6、创建弹窗对象并将弹窗添加到地图中

          this.map = new Map({
            //地图容器ID
            target: "map",
            //引入地图
            layers: [this.layer,this.lightLayer,this.houseLayer,this.lineLayer],
            view: new View({
              //地图中心点
              center: [987777.93778, 213834.81024],
              zoom: 12,
              minZoom:6, // 地图缩放最小级别
              maxZoom:19,
              rotation: 0.76
            }),
          });
    
          // 将弹窗添加到 map 地图中
          this.map.addOverlay(this.overlay);

    7、监听地图的单击事件,在回调函数中获取坐标值并将内容赋值给dom

    并且设置弹窗的位置就是当前鼠标点击的位置

          // 将弹窗添加到 map 地图中
          this.map.addOverlay(this.overlay);
          //必须 要重新赋值this,不然再回调函数中指针会变,overlay会undefined
          let _that = this;
          // 监听singleclick事件
          this.map.on('singleclick', function(e) {
            let coordinate = e.coordinate
            // 点击尺 (这里是尺(米),并不是经纬度);
            let hdms = toStringHDMS(toLonLat(e.coordinate)); // 转换为经纬度显示
            content.innerHTML = `
            <p>你点击了这里:</p>
            <p>经纬度:<p><code> ${hdms}  </code> <p>
            <p>坐标:</p>X:${coordinate[0]} &nbsp;&nbsp; Y: ${coordinate[1]}`;
            _that.overlay.setPosition(coordinate); //把 overlay 显示到指定的 x,y坐标
            console.log(e.coordinate)
            })

    8、这里尤其要注意的是,单击事件的回调方法中要对overplay设置其显示位置

    这里不能再直接使用this.overplay.setPosition了,因为在回调函数中指针会变,

    此时会提示overlay为undefined。所以先重新赋值再使用

    let _that = this;

    _that.overlay.setPosition(coordinate); //把 overlay 显示到指定的 x,y坐标

    7、设置弹窗关闭事件

    将overlay对象的setPosition赋值为undefined即可隐藏。

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

    8、完整示例代码

    <template>
        <div id="app">
          <div id="map" class="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>
        </div>
    </template>
    
    <script>
    //导入基本模块
    import "ol/ol.css";
    import Map from "ol/Map";
    import Overlay from "ol/Overlay";
    import View from "ol/View";
    import { Point,LineString } from "ol/geom";
    import Feature from "ol/Feature";
    import { Icon,Style,Stroke} from "ol/style";
    //导入相关模块
    import { Tile as TileLayer , Vector as VectorLayer } from 'ol/layer'
    import { TileWMS ,Vector as VectorSource } from 'ol/source'
    import { toStringHDMS } from "ol/coordinate";
    import { toLonLat } from "ol/proj";
    export default {
      name: "olMapImageWMSMulLayers",
      data() {
        return {
          map: null, // map地图
          layer:null, //地图图层
          lightLayer:null, //灯图层
          houseLayer:null, //房子图层
          lineLayer:null, //线图层
          lineSource:null, //线数据源
          overlay: null,
          container: null, // 弹框
          //红绿灯数据
          lightData:[
            {x:"987798.93778", y:"213885.81024"},
            {x:"987710.93778", y:"213810.81024"},
          ],
          //房子数据
          houseData:[
            {x:"986610.93778", y:"213885.81024"},
            {x:"986510.93778", y:"213810.81024"},
          ],
          //线的数据
          lineData:[
            [986434.4063822062, 215782.0959711917],
            [989701.5290279881,217149.84072807242],
            [990613.3107184113,215946.4192185118],
          ],
       };
      },
      mounted() {
        this.initMap();
        setInterval(() => {
          this.initLightData();
        }, 1000)
      },
      methods: {
    
        //初始化红绿灯数据
        initLightData(){
          this.lightLayer.getSource().clear();
          this.lightData.forEach((item, index) => {
              var feature = new Feature({
                  geometry: new Point([Number(item.x), Number(item.y)]),
              });
              let url = "images/light.png";
              const zoom = this.map.getView().getZoom();
              let style = new Style({
                      image: new Icon({
                          scale: 0.15 * (zoom -13) ,
                          src: url,
                          anchor: [0.48, 0.52],
                      }),
                  });
              feature.setStyle(style);
              this.lightLayer.getSource().addFeature(feature);
          });
        },
    
        //初始化房子数据
        initHouseData(){
          this.houseLayer.getSource().clear();
          this.houseData.forEach((item, index) => {
              var feature = new Feature({
                  geometry: new Point([Number(item.x), Number(item.y)]),
              });
              let url = "images/house.png";
              let style = new Style({
                      image: new Icon({
                          scale: 0.3,
                          src: url,
                          anchor: [0.48, 0.52],
                      }),
                  });
              feature.setStyle(style);
              this.houseLayer.getSource().addFeature(feature);
          });
        },
    
        //画线
        drawLine(){
          let pointData = this.lineData; // 所有点位信息
          //下边来添加一线feature
          var feature = new Feature({
              type: "lineStyle",
              geometry: new LineString(
                  pointData // 线的坐标
              ),
          });
          let color = 'green';
          let lineStyle = new Style({
              stroke: new Stroke({
                  color: color,
                   4,
              }),
          });
          // 添加线的样式
          feature.setStyle(lineStyle);
          // 添加线的fature
          this.lineSource.addFeature(feature);
        },
        initMap() {
    
          // 获取到弹框的节点DOM
          var container = document.getElementById("popup");
          var content = document.getElementById("popup-content");
          var closer = document.getElementById("popup-closer");
    
          //地图图层
          this.layer = new TileLayer({
            source: new TileWMS({
              //不能设置为0,否则地图不展示。
              ratio: 1,
              url: "http://localhost:8000/geoserver/nyc/wms",
              params: {
                LAYERS: "nyc:nyc_roads",
                STYLES: "",
                VERSION: "1.1.1",
                tiled: true
              },
              serverType: "geoserver",
            }),
          });
    
          // 红绿灯的图层
          this.lightLayer = new VectorLayer({
              source: new VectorSource(),
          });
         
          //房子的图层
          this.houseLayer = new VectorLayer({
              source: new VectorSource(),
          });
    
          //线的图层
          this.lineSource = new VectorSource({ wrapX: false });
          this.lineLayer = new VectorLayer({
              source: this.lineSource,
          });
    
          // 创建一个弹窗 Overlay 对象
          this.overlay = new Overlay({
              element: container, //绑定 Overlay 对象和 DOM 对象的
              autoPan: true, // 定义弹出窗口在边缘点击时候可能不完整 设置自动平移效果
              autoPanAnimation: {
                  duration: 250 //自动平移效果的动画时间 9毫秒
              }
          });
    
          this.map = new Map({
            //地图容器ID
            target: "map",
            //引入地图
            layers: [this.layer,this.lightLayer,this.houseLayer,this.lineLayer],
            view: new View({
              //地图中心点
              center: [987777.93778, 213834.81024],
              zoom: 12,
              minZoom:6, // 地图缩放最小级别
              maxZoom:19,
              rotation: 0.76
            }),
          });
    
          // 将弹窗添加到 map 地图中
          this.map.addOverlay(this.overlay);
          //必须 要重新赋值this,不然再回调函数中指针会变,overlay会undefined
          let _that = this;
          // 监听singleclick事件
          this.map.on('singleclick', function(e) {
            let coordinate = e.coordinate
            // 点击尺 (这里是尺(米),并不是经纬度);
            let hdms = toStringHDMS(toLonLat(e.coordinate)); // 转换为经纬度显示
            content.innerHTML = `
            <p>你点击了这里:</p>
            <p>经纬度:<p><code> ${hdms}  </code> <p>
            <p>坐标:</p>X:${coordinate[0]} &nbsp;&nbsp; Y: ${coordinate[1]}`;
            _that.overlay.setPosition(coordinate); //把 overlay 显示到指定的 x,y坐标
            console.log(e.coordinate)
            })
          //弹窗关闭事件
          closer.onclick=function(){
            _that.overlay.setPosition(undefined);
            closer.blur();
            return false;
          };
          this.initLightData();
          this.initHouseData();
          this.drawLine();
    
        },
      },
    };
    </script>
    
    <style scoped>
    .map {
       100%;
      height: 800px;
    }
    .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>
  • 相关阅读:
    Java小案例——对字符串进行加密解密
    Java基础——使用三元运算符判断一个数的奇偶性
    Java基础——字母大小写转换
    多线程实现——新龟兔赛跑
    编程面试题之——简答题(持续更新...)
    多线程之——共享数据
    多线程之——线程的状态
    Android 8.0 Oreo介绍
    Android 7.0 Nougat介绍
    Android 6.0 Marshmallow介绍
  • 原文地址:https://www.cnblogs.com/badaoliumangqizhi/p/15540234.html
Copyright © 2011-2022 走看看