Vue+OpenLayer實現(xiàn)測距功能
前言
首先呢說明一下,我是跟著一個大佬學的,所以我是個小次佬,openlayer的官網(wǎng)上面給出了案例,但是習慣vue開發(fā)的我完全不理解,關(guān)鍵是連注釋都沒多少,而且我 openlayer 用的本來就不多。
然后這里分享一下官網(wǎng)的測距案例
引入相關(guān)庫文件
這個庫文件直接按照官網(wǎng)的來就可以了。 首先說一個事情哈,官網(wǎng)用的案例是地圖使用的 EPSG:3857, 如果我們改成 EPSG:4326,測量數(shù)據(jù)不準確,切記這一點。
import 'ol/ol.css'; import Draw from 'ol/interaction/Draw'; import Map from 'ol/Map'; import Overlay from 'ol/Overlay'; import View from 'ol/View'; import { Circle as CircleStyle, Fill, Stroke, Style } from 'ol/style'; import { LineString, Polygon } from 'ol/geom'; import { OSM, Vector as VectorSource } from 'ol/source'; import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer'; import { getArea, getLength } from 'ol/sphere'; import { unByKey } from 'ol/Observable';
上面是我引入的庫文件,和官網(wǎng)基本上一樣。
繪制提示文字
首先我們看下圖官網(wǎng)效果,官網(wǎng)開始繪制或者是繪制中都在鼠標旁邊有一個title文本框用來提示用戶操作信息。
我們首先來實現(xiàn)一下這個功能。
首先說明一點哈,這是關(guān)鍵代碼,有些參數(shù)可能用起來發(fā)現(xiàn)沒有聲明,都是全局的,自己加在全局就可以,主要是下面這一些。
var map = null var helpTooltipElement = null var feature = null; var helpTooltip = null; var draw = null; var measureTooltipElement = null; var measureTooltip = null; var listener = null; var mapMouseMove = null;
首先我們在需要實現(xiàn)測距功能的頁面上寫兩個按鈕,一個開始測距,一個結(jié)束測距。然后點擊開始測距的時候,執(zhí)行一個方法,假設(shè)是distance方法。
distance() { let source = new VectorSource() // 首先創(chuàng)建一個數(shù)據(jù)源,用來放置繪制過程中和繪制結(jié)束后的線段 const layer = new VectorLayer({ // 添加一個圖層,用來放置數(shù)據(jù)源,樣式自己隨便設(shè)置就可以了,我這里默認的官網(wǎng) source: source, style: new Style({ fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)', }), stroke: new Stroke({ color: '#ffcc33', width: 4, }), image: new CircleStyle({ radius: 7, fill: new Fill({ color: '#ffcc33', }), }), }), }); mapMouseMove = map.on('pointermove', (ev) => { // 給地圖添加一個鼠標移動事件 let helpMsg = '點擊開始測量' // 默認開始的操作提示文本 if (feature) { // featuer 是全局的,判斷有沒有點擊鼠標繪制過 helpMsg = '雙擊結(jié)束測量' // 如果之前點擊繪制了就顯示雙擊結(jié)束 } helpTooltipElement.innerHTML = helpMsg; // 設(shè)置dom的提示文字 helpTooltip.setPosition(ev.coordinate); // 設(shè)置位置跟著鼠標走 helpTooltipElement.classList.remove('hidden') // 讓他顯示出來 }) this.createHelpTooltip() // 創(chuàng)建那個helpTooltipElement方法 map.addLayer(layer) // 把圖層添加到地圖 },
然后調(diào)用了一個初始化操作提示的dom元素。這個就是官網(wǎng)的函數(shù),如果參數(shù)名和自己起的或者是map的指向問題需要自己根據(jù)自己的實際修改一下。
createHelpTooltip() { if (helpTooltipElement) { helpTooltipElement.parentNode.removeChild(helpTooltipElement); } helpTooltipElement = document.createElement('div'); helpTooltipElement.className = 'ol-tooltip hidden'; helpTooltip = new Overlay({ element: helpTooltipElement, offset: [15, 0], positioning: 'center-left', }); map.addOverlay(helpTooltip); },
還有一點,為了好看,把官網(wǎng)的樣式復制一下子。
<style scoped> /deep/.ol-tooltip { position: relative; background: rgba(0, 0, 0, 0.5); border-radius: 4px; color: white; padding: 4px 8px; opacity: 0.7; white-space: nowrap; font-size: 12px; cursor: default; user-select: none; } /deep/.ol-tooltip-measure { opacity: 1; font-weight: bold; } /deep/.ol-tooltip-static { background-color: #ffcc33; color: black; border: 1px solid white; } /deep/.ol-tooltip-measure:before, /deep/.ol-tooltip-static:before { border-top: 6px solid rgba(0, 0, 0, 0.5); border-right: 6px solid transparent; border-left: 6px solid transparent; content: ""; position: absolute; bottom: -6px; margin-left: -7px; left: 50%; } /deep/.ol-tooltip-static:before { border-top-color: #ffcc33; } </style>
然后就可以看到我們點擊“開始測距”按鈕之后,上面代碼執(zhí)行,鼠標旁邊就出現(xiàn)一個小小的操作提示。
鼠標繪制線
好的,通過上面的代碼呢,我們成功的繪制出了提示框,然后就是鼠標繪制,代碼也很簡單,在map監(jiān)聽的pointermove方法中,繼續(xù)創(chuàng)建一個draw進行繪制,關(guān)鍵代碼就是下面:
draw = new Draw({ source, // 這個數(shù)據(jù)源就是我們最開始的那個數(shù)據(jù)源,這是簡寫,實際上是 source:source, type: 'LineString', // 繪制線 style: new Style({ // 繪制完成之前線的樣式,這是官網(wǎng)的樣式,需要的話自己可以修改成自己想要的樣子 fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)', }), stroke: new Stroke({ color: 'rgba(0, 0, 0, 0.5)', lineDash: [10, 10], width: 4, }), image: new CircleStyle({ radius: 5, stroke: new Stroke({ color: 'rgba(0, 0, 0, 0.7)', }), fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)', }), }), }), });
然后把draw綁定到地圖上面。
map.addInteraction(draw); // draw 綁定到地圖上面去
然后就實現(xiàn)了鼠標繪制線。
設(shè)置距離信息窗
在我們點擊開始測量的時候呢,在我們拖動鼠標的時候,會在上方顯示出當前距離起點的距離,這個地方代碼實現(xiàn)就是下面的樣子,繼續(xù)在上面的代碼后面寫:
// 開始監(jiān)聽繪制 draw.on('drawstart', (evt) => { feature = evt.feature; // feature就是全局的 let tooltipCoord = evt.coordinate; // 鼠標當前的位置 listener = feature.getGeometry().on('change', function (evt) { const geom = evt.target; let output = formatLength(geom); // 距離的格式 tooltipCoord = geom.getLastCoordinate(); // 設(shè)置鼠標位置改變后的實時位置 measureTooltipElement.innerHTML = output; // 設(shè)置提示框的內(nèi)容,就是距離 measureTooltip.setPosition(tooltipCoord); // 設(shè)置距離提示框的位置 }); }); // 格式化長度, 直接官網(wǎng)代碼 const formatLength = function (line) { const length = getLength(line); let output; if (length > 100) { output = Math.round((length / 1000) * 100) / 100 + ' ' + 'km'; } else { output = Math.round(length * 100) / 100 + ' ' + 'm'; } return output; }; this.createMeasureTooltip() // 創(chuàng)建那個距離的提示框
然后上面代碼調(diào)用了一個方法。
createMeasureTooltip() { if (measureTooltipElement) { measureTooltipElement.parentNode.removeChild(measureTooltipElement); } measureTooltipElement = document.createElement('div'); measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure'; measureTooltip = new Overlay({ element: measureTooltipElement, offset: [0, -15], positioning: 'bottom-center', stopEvent: false, insertFirst: false, }); this.drawElements.push(measureTooltip) map.addOverlay(measureTooltip); },
完成上面的代碼之后,我們在點擊開始測量之后,會在鼠標上方實時顯示當前鼠標位置距離起點的距離。
繪制完成
上邊已經(jīng)實現(xiàn)了點擊開始測距,并且實時顯示距離信息,接下來就是雙擊完成時候顯示出總長度。
繼續(xù)在之前代碼后邊寫:
// 雙擊繪制完成 draw.on('drawend', () => { measureTooltipElement.className = 'ol-tooltip ol-tooltip-static'; measureTooltip.setOffset([0, -7]); feature = null; measureTooltipElement = null; this.createMeasureTooltip(); unByKey(listener); });
上邊的代碼基本上就是官網(wǎng)的代碼,但是變量名不一樣的地方需要稍微改一下。
通過上面的代碼就實現(xiàn)了雙擊測量完成的功能。
OK,到此為止,測距功能全部完成!
取消繪制
繪制功能完成了,就需要取消繪制,取消繪制需要在點擊“取消繪制”按鈕之后,取消地圖繪制功能,刪除界面上已經(jīng)繪制過的內(nèi)容。
首先我們需要刪除地圖上繪制過的內(nèi)容,包括連線,以及彈窗。
這個地方需要注意一下,我們需要把繪制的圖層,比如連線,和彈窗都保存到一個或者是幾個列表里面,然后在點擊按鈕的時候,去遍歷刪除。
所以說我們要在點擊測距時候加載到地圖的圖層之后,將創(chuàng)建的圖層添加到一個數(shù)組存起來。
map.addLayer(layer) this.drawLayers.push(layer) // 保存起來
包括那個總距離的彈窗。
this.drawElements.push(measureTooltip) map.addOverlay(measureTooltip); // 保存起來
然后點擊“取消測量”按鈕的時候執(zhí)行下面的代碼:
// 取消繪制 cancal() { for(let i = 0 ; i< this.drawLayers.length; i++) { map.removeLayer(this.drawLayers[i]) } for (let i = 0; i < this.drawElements.length; i++) { map.removeOverlay(this.drawElements[i]) } this.drawLayers = [] this.drawElements = [] map.removeInteraction(draw) unByKey(mapMouseMove); },
這樣就可以了。
這樣就完成了!
全部代碼
這里分享一下全部代碼,就不放資源了,下載還花錢,我也是跟人家學的,沒必要都。
<template> <div class="home"> <div class="set"> <button class="btn" @click="distance()">測距</button> <button class="btn" @click="cancal()">取消</button> </div> <div id="map" ref="map"></div> </div> </template> <script> import 'ol/ol.css'; import Draw from 'ol/interaction/Draw'; import Map from 'ol/Map'; import Overlay from 'ol/Overlay'; import View from 'ol/View'; import { Circle as CircleStyle, Fill, Stroke, Style } from 'ol/style'; import { LineString, Polygon } from 'ol/geom'; import { OSM, Vector as VectorSource } from 'ol/source'; import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer'; import { getArea, getLength } from 'ol/sphere'; import { unByKey } from 'ol/Observable'; var map = null var helpTooltipElement = null var feature = null; var helpTooltip = null; var draw = null; var measureTooltipElement = null; var measureTooltip = null; var listener = null; var mapMouseMove = null; export default { name: "Home", data() { return { drawLayers: [], drawElements: [], } }, mounted() { this.initMap() }, methods: { // 初始化地圖 initMap() { map = new Map({ layers: [ new TileLayer({ source: new OSM(), }), ], target: 'map', view: new View({ center: [0, 0], zoom: 5, maxZoom: 18, // projection: 'EPSG:4326', constrainResolution: true, // 設(shè)置縮放級別為整數(shù) smoothResolutionConstraint: false, // 關(guān)閉無級縮放地圖 }), }); }, // 測距 distance() { let source = new VectorSource() const layer = new VectorLayer({ source: source, style: new Style({ fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)', }), stroke: new Stroke({ color: '#ffcc33', width: 4, }), image: new CircleStyle({ radius: 7, fill: new Fill({ color: '#ffcc33', }), }), }), }); mapMouseMove = map.on('pointermove', (ev) => { let helpMsg = '點擊開始測量' if (feature) { helpMsg = '雙擊結(jié)束測量' } helpTooltipElement.innerHTML = helpMsg; helpTooltip.setPosition(ev.coordinate); helpTooltipElement.classList.remove('hidden') }) map.getViewport().addEventListener('mouseout', function () { helpTooltipElement.classList.add('hidden'); }); draw = new Draw({ source, type: 'LineString', style: new Style({ fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)', }), stroke: new Stroke({ color: 'rgba(0, 0, 0, 0.5)', lineDash: [10, 10], width: 4, }), image: new CircleStyle({ radius: 5, stroke: new Stroke({ color: 'rgba(0, 0, 0, 0.7)', }), fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)', }), }), }), }); // 開始堅挺繪制 draw.on('drawstart', (evt) => { feature = evt.feature; let tooltipCoord = evt.coordinate; listener = feature.getGeometry().on('change', function (evt) { const geom = evt.target; let output = formatLength(geom); tooltipCoord = geom.getLastCoordinate(); measureTooltipElement.innerHTML = output; measureTooltip.setPosition(tooltipCoord); }); }); // 雙擊繪制完成 draw.on('drawend', () => { measureTooltipElement.className = 'ol-tooltip ol-tooltip-static'; measureTooltip.setOffset([0, -7]); feature = null; measureTooltipElement = null; this.createMeasureTooltip(); unByKey(listener); }); // 格式化長度 const formatLength = function (line) { const length = getLength(line); let output; if (length > 100) { output = Math.round((length / 1000) * 100) / 100 + ' ' + 'km'; } else { output = Math.round(length * 100) / 100 + ' ' + 'm'; } return output; }; this.createHelpTooltip() this.createMeasureTooltip() map.addLayer(layer) this.drawLayers.push(layer) map.addInteraction(draw); }, // 取消繪制 cancal() { for(let i = 0 ; i< this.drawLayers.length; i++) { map.removeLayer(this.drawLayers[i]) } for (let i = 0; i < this.drawElements.length; i++) { map.removeOverlay(this.drawElements[i]) } this.drawLayers = [] this.drawElements = [] map.removeInteraction(draw) unByKey(mapMouseMove); }, createMeasureTooltip() { if (measureTooltipElement) { measureTooltipElement.parentNode.removeChild(measureTooltipElement); } measureTooltipElement = document.createElement('div'); measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure'; measureTooltip = new Overlay({ element: measureTooltipElement, offset: [0, -15], positioning: 'bottom-center', stopEvent: false, insertFirst: false, }); this.drawElements.push(measureTooltip) map.addOverlay(measureTooltip); }, createHelpTooltip() { if (helpTooltipElement) { helpTooltipElement.parentNode.removeChild(helpTooltipElement); } helpTooltipElement = document.createElement('div'); helpTooltipElement.className = 'ol-tooltip hidden'; helpTooltip = new Overlay({ element: helpTooltipElement, offset: [15, 0], positioning: 'center-left', }); map.addOverlay(helpTooltip); }, }, }; </script> <style scoped> .home { width: 100%; height: 100%; background-color: aliceblue; position: relative; } #map { height: 100%; width: 100%; } .set { position: absolute; top: 0px; right: 0px; z-index: 99; } .btn { margin: 10px; } /deep/.hidden { display: none; } /deep/.ol-tooltip { position: relative; background: rgba(0, 0, 0, 0.5); border-radius: 4px; color: white; padding: 4px 8px; opacity: 0.7; white-space: nowrap; font-size: 12px; cursor: default; user-select: none; } /deep/.ol-tooltip-measure { opacity: 1; font-weight: bold; } /deep/.ol-tooltip-static { background-color: #ffcc33; color: black; border: 1px solid white; } /deep/.ol-tooltip-measure:before, /deep/.ol-tooltip-static:before { border-top: 6px solid rgba(0, 0, 0, 0.5); border-right: 6px solid transparent; border-left: 6px solid transparent; content: ""; position: absolute; bottom: -6px; margin-left: -7px; left: 50%; } /deep/.ol-tooltip-static:before { border-top-color: #ffcc33; } </style>
以上就是Vue+OpenLayer實現(xiàn)測距功能 的詳細內(nèi)容,更多關(guān)于Vue OpenLayer測距的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue Promise解決回調(diào)地獄問題實現(xiàn)方法
這篇文章主要介紹了Vue Promise解決回調(diào)地獄問題,總的來說這并不是一道難題,那為什么要拿出這道題介紹?拿出這道題真正想要傳達的是解題的思路,以及不斷優(yōu)化探尋最優(yōu)解的過程。希望通過這道題能給你帶來一種解題優(yōu)化的思路2023-01-01Vue transition實現(xiàn)點贊動畫效果的示例
點贊動畫是網(wǎng)頁評論中常見的功能,本文將介紹如何用vue實現(xiàn)這一效果。點贊時愛心縮小變大,變大時略微大一點再變正常,取消點贊時愛心無動畫,同時數(shù)字滾動,+1 時向上滾動,-1 時向下滾動2021-05-05關(guān)于axios配置多個請求地址(打包后可通過配置文件修改)
這篇文章主要介紹了關(guān)于axios配置多個請求地址(打包后可通過配置文件修改),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09vue跳轉(zhuǎn)同一個組件,參數(shù)不同,頁面接收值只接收一次的解決方法
今天小編就為大家分享一篇vue跳轉(zhuǎn)同一個組件,參數(shù)不同,頁面接收值只接收一次的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11