Openlayers中使用Overlay实现点击要素弹窗并且弹窗随之移动
場景
Vue+Openlayer使用overlay實現彈窗彈出顯示與關閉:
Vue+Openlayer使用overlay實現彈窗彈出顯示與關閉_BADAO_LIUMANG_QIZHI的博客-CSDN博客
實現彈窗的效果可以參考上面。
要實現的效果是點擊某個元素彈窗顯示,并且彈窗隨著元素的移動而移動。
實現元素移動的效果可以參考如下:
Openlayers中使用Image的rotation實現車輛定位導航帶轉角(判斷車輛圖片旋轉角度):
Openlayers中使用Image的rotation實現車輛定位導航帶轉角(判斷車輛圖片旋轉角度)_BADAO_LIUMANG_QIZHI的博客-CSDN博客
結合以上兩個的效果
注:
博客:
BADAO_LIUMANG_QIZHI的博客_霸道流氓氣質_CSDN博客-C#,SpringBoot,架構之路領域博主
關注公眾號
霸道的程序猿
獲取編程相關電子書、教程推送與免費下載。
實現
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;width: 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 {width: 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});//定位圖層的Sourcevar 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]]//下邊來添加一線featurevar 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',width: 4})})// 添加線的樣式feature.setStyle(lineStyle)// 添加線的fatureself.drwaSource.addFeature(feature)}//清除線的方法function clearLine() {this.drwaSource.clear();}// 獲取到彈框的節點DOMvar 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);//添加feturethis.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.xvar dy = second.y - first.yvar rotation = Math.atan2(dy, dx)return rotation}</script> </body></html>總結
以上是生活随笔為你收集整理的Openlayers中使用Overlay实现点击要素弹窗并且弹窗随之移动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Openlayers中使用Cluster
- 下一篇: Vue+Openlayers实现加载天地