場景
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]} 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]} 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>
