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 {
  width: 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 {
    width: 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,
              width: 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 {
  width: 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 {
    width: 400px;
}
.ol-popup-closer {
    text-decoration: none;
    position: absolute;
    top: 2px;
    right: 8px;
}
</style>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM