最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue+OpenLayer實(shí)現(xiàn)測距功能

 更新時(shí)間:2022年04月20日 14:19:27   作者:秦浩鋮  
OpenLayers?是一個(gè)專為Web?GIS?客戶端開發(fā)提供的JavaScript?類庫包,用于實(shí)現(xiàn)標(biāo)準(zhǔn)格式發(fā)布的地圖數(shù)據(jù)訪問。本文將通過Vue和OpenLayer實(shí)現(xiàn)測距功能?,需要的可以參考一下

前言

首先呢說明一下,我是跟著一個(gè)大佬學(xué)的,所以我是個(gè)小次佬,openlayer的官網(wǎng)上面給出了案例,但是習(xí)慣vue開發(fā)的我完全不理解,關(guān)鍵是連注釋都沒多少,而且我 openlayer 用的本來就不多。

然后這里分享一下官網(wǎng)的測距案例

引入相關(guān)庫文件

這個(gè)庫文件直接按照官網(wǎng)的來就可以了。 首先說一個(gè)事情哈,官網(wǎng)用的案例是地圖使用的 EPSG:3857, 如果我們改成 EPSG:4326,測量數(shù)據(jù)不準(zhǔn)確,切記這一點(diǎn)。

  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)開始繪制或者是繪制中都在鼠標(biāo)旁邊有一個(gè)title文本框用來提示用戶操作信息。

我們首先來實(shí)現(xiàn)一下這個(gè)功能。

首先說明一點(diǎ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;

首先我們在需要實(shí)現(xiàn)測距功能的頁面上寫兩個(gè)按鈕,一個(gè)開始測距,一個(gè)結(jié)束測距。然后點(diǎn)擊開始測距的時(shí)候,執(zhí)行一個(gè)方法,假設(shè)是distance方法。

  distance() {
        let source = new VectorSource()  // 首先創(chuàng)建一個(gè)數(shù)據(jù)源,用來放置繪制過程中和繪制結(jié)束后的線段
        const layer = new VectorLayer({  // 添加一個(gè)圖層,用來放置數(shù)據(jù)源,樣式自己隨便設(shè)置就可以了,我這里默認(rèn)的官網(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) => {  // 給地圖添加一個(gè)鼠標(biāo)移動事件
          let helpMsg = '點(diǎn)擊開始測量'    // 默認(rèn)開始的操作提示文本
          if (feature) {  // featuer 是全局的,判斷有沒有點(diǎn)擊鼠標(biāo)繪制過
            helpMsg = '雙擊結(jié)束測量'    // 如果之前點(diǎn)擊繪制了就顯示雙擊結(jié)束
          }
          helpTooltipElement.innerHTML = helpMsg;   // 設(shè)置dom的提示文字
          helpTooltip.setPosition(ev.coordinate);  // 設(shè)置位置跟著鼠標(biāo)走
          helpTooltipElement.classList.remove('hidden')  // 讓他顯示出來
        })
        this.createHelpTooltip()   // 創(chuàng)建那個(gè)helpTooltipElement方法
        map.addLayer(layer)  // 把圖層添加到地圖
      },

然后調(diào)用了一個(gè)初始化操作提示的dom元素。這個(gè)就是官網(wǎng)的函數(shù),如果參數(shù)名和自己起的或者是map的指向問題需要自己根據(jù)自己的實(shí)際修改一下。

      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);
      },

還有一點(diǎn),為了好看,把官網(wǎng)的樣式復(fù)制一下子。

<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>

然后就可以看到我們點(diǎn)擊“開始測距”按鈕之后,上面代碼執(zhí)行,鼠標(biāo)旁邊就出現(xiàn)一個(gè)小小的操作提示。

鼠標(biāo)繪制線

好的,通過上面的代碼呢,我們成功的繪制出了提示框,然后就是鼠標(biāo)繪制,代碼也很簡單,在map監(jiān)聽的pointermove方法中,繼續(xù)創(chuàng)建一個(gè)draw進(jìn)行繪制,關(guān)鍵代碼就是下面:

		draw = new Draw({
          source,  // 這個(gè)數(shù)據(jù)源就是我們最開始的那個(gè)數(shù)據(jù)源,這是簡寫,實(shí)際上是 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 綁定到地圖上面去

然后就實(shí)現(xiàn)了鼠標(biāo)繪制線。

設(shè)置距離信息窗

在我們點(diǎn)擊開始測量的時(shí)候呢,在我們拖動鼠標(biāo)的時(shí)候,會在上方顯示出當(dāng)前距離起點(diǎn)的距離,這個(gè)地方代碼實(shí)現(xiàn)就是下面的樣子,繼續(xù)在上面的代碼后面寫:

		// 開始監(jiān)聽繪制
        draw.on('drawstart', (evt) => {
          feature = evt.feature;  // feature就是全局的
          let tooltipCoord = evt.coordinate;  // 鼠標(biāo)當(dāng)前的位置 
          listener = feature.getGeometry().on('change', function (evt) {
            const geom = evt.target;
            let output = formatLength(geom);   // 距離的格式
            tooltipCoord = geom.getLastCoordinate();    // 設(shè)置鼠標(biāo)位置改變后的實(shí)時(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)建那個(gè)距離的提示框

然后上面代碼調(diào)用了一個(gè)方法。

	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);
      },

完成上面的代碼之后,我們在點(diǎn)擊開始測量之后,會在鼠標(biāo)上方實(shí)時(shí)顯示當(dāng)前鼠標(biāo)位置距離起點(diǎn)的距離。

繪制完成

上邊已經(jīng)實(shí)現(xiàn)了點(diǎn)擊開始測距,并且實(shí)時(shí)顯示距離信息,接下來就是雙擊完成時(shí)候顯示出總長度。

繼續(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)的代碼,但是變量名不一樣的地方需要稍微改一下。

通過上面的代碼就實(shí)現(xiàn)了雙擊測量完成的功能。

OK,到此為止,測距功能全部完成!

取消繪制

繪制功能完成了,就需要取消繪制,取消繪制需要在點(diǎn)擊“取消繪制”按鈕之后,取消地圖繪制功能,刪除界面上已經(jīng)繪制過的內(nèi)容。

首先我們需要刪除地圖上繪制過的內(nèi)容,包括連線,以及彈窗。

這個(gè)地方需要注意一下,我們需要把繪制的圖層,比如連線,和彈窗都保存到一個(gè)或者是幾個(gè)列表里面,然后在點(diǎn)擊按鈕的時(shí)候,去遍歷刪除。

所以說我們要在點(diǎn)擊測距時(shí)候加載到地圖的圖層之后,將創(chuàng)建的圖層添加到一個(gè)數(shù)組存起來。

map.addLayer(layer)
this.drawLayers.push(layer)  // 保存起來

包括那個(gè)總距離的彈窗。

this.drawElements.push(measureTooltip)
map.addOverlay(measureTooltip);  // 保存起來

然后點(diǎn)擊“取消測量”按鈕的時(shí)候執(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);
      },

這樣就可以了。

這樣就完成了!

全部代碼

這里分享一下全部代碼,就不放資源了,下載還花錢,我也是跟人家學(xué)的,沒必要都。

<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 = '點(diǎn)擊開始測量'
          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)',
              }),
            }),
          }),
        });

        // 開始堅(jiān)挺繪制
        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實(shí)現(xiàn)測距功能 的詳細(xì)內(nèi)容,更多關(guān)于Vue OpenLayer測距的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

永胜县| 阳原县| 麻阳| 扶绥县| 如东县| 图们市| 邢台县| 客服| 崇阳县| 金山区| 辛集市| 沙湾县| 石景山区| 尉氏县| 舞阳县| 安达市| 贵南县| 察隅县| 林周县| 阜阳市| 酒泉市| 略阳县| 平阴县| 祁门县| 察雅县| 明水县| 德昌县| 长海县| 乐业县| 分宜县| 乌拉特后旗| 大埔县| 河北省| 盱眙县| 鄂伦春自治旗| 东辽县| 南溪县| 台东县| 安仁县| 乐至县| 苗栗市|