Vue+Openlayers實現繪制線段並測量距離顯示


場景

Vue+Openlayer使用Draw實現交互式繪制線段:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/121287934

在上面已經實現交互式繪制線段基礎上,怎樣實現測量距離。

 

 

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi
關注公眾號
霸道的程序猿
獲取編程相關電子書、教程推送與免費下載。

實現

1、頁面上添加按鈕與map

<template>
  <div>
    <div>
      <el-button type="primary" @click="beginCalDistance">開始測距</el-button>
      <el-button type="primary" @click="cancleCalDistance">取消測距</el-button>
    </div>
    <div id="app">
      <div id="map" class="map"></div>
    </div>
  </div>
</template>

2、引入相關依賴

//導入基本模塊
import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import { Fill, Style, Stroke } from "ol/style";
//導入相關模塊
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { TileWMS, Vector as VectorSource } from "ol/source";
import { Select, Draw } from "ol/interaction";
import { getLength } from "ol/sphere";
import { LineString } from "ol/geom";
import Overlay from "ol/Overlay";

3、聲明變量

export default {
  name: "olMapImageWMSDrawLineAndCalDistance",
  data() {
    return {
      map: null, // map地圖
      layer: null, //地圖圖層
      lineLayer: null, //線圖層
      draw: null,
      lineSource: null,
      coordinate: [],
      measureTooltipElement: null,
      measureTooltip: null,
      sketch: null,
      geom: null,
    };
  },

4、在頁面初始化之后調用初始化地圖的方法

    //初始化地圖
    initMap() {
      //地圖圖層
      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.lineSource = new VectorSource({ wrapX: false });
      this.lineLayer = new VectorLayer({
        source: this.lineSource,
      });

      this.map = new Map({
        //地圖容器ID
        target: "map",
        //引入地圖
        layers: [this.layer, this.lineLayer],
        view: new View({
          //地圖中心點
          center: [987777.93778, 213834.81024],
          zoom: 14,
          minZoom: 6, // 地圖縮放最小級別
          maxZoom: 19,
        }),
      });
    },

5、開始測試按鈕的點擊事件中

    //開始測距
    beginCalDistance() {
      //調用繪圖工具並傳遞類型為線,其他類型有Point,LineString,Polygon,Circle
      this.onAddInteraction("LineString");
      //創建一個新的測距提示
      this.createMeasureTooltip();
    },

調用繪圖功能並傳遞類型為線以及給地圖添加交互onAddInteraction方法

 

  // 繪圖工具
    onAddInteraction(type) {
      let self = this;
      //勾繪矢量圖形的類
      this.draw = new Draw({
        //source代表勾繪的要素屬於的數據集
        source: self.lineSource,
        //type 表示勾繪的要素包含的 geometry 類型
        type: type,
      });

      //繪制開始時觸發的事件
      this.draw.on("drawstart", function (evt) {
        self.sketch = evt.feature;
        //提示框的坐標
        var tooltipCoord = evt.coordinate;
        //定義一個事件監聽,監聽幾何要素的change事件
        var listener = self.sketch.getGeometry().on("change", function (evt) {
          //獲取繪制的幾何對象
          self.geom = evt.target;
          //定義一個輸出對象,用於記錄長度
          var output;
          //判斷交互類型是否為線
          if (self.geom instanceof LineString) {
            //輸出多線段的長度
            output = self.formatLength(self.geom);
            //獲取多線段的最后一個點的坐標
            tooltipCoord = self.geom.getLastCoordinate();
          }
          //設置測量提示框的內標簽為最終輸出結果
          self.measureTooltipElement.innerHTML = output;
          self.measureTooltipElement.className =
            "ol-tooltip ol-tooltip-static draw_km";
          //設置測量提示框的位置坐標
          self.measureTooltip.setPosition(tooltipCoord);
        });
      });

      //繪制結束時觸發的事件
      this.draw.on("drawend", function (e) {
        //輸出坐標信息
        const geometry = e.feature.getGeometry();
        let pointArr = geometry.getCoordinates();
        self.coordinate.push(pointArr);
        console.log("self.coordinate=" + self.coordinate);
        //移除交互
        self.removeDraw();
      });

      //添加交互
      self.map.addInteraction(this.draw);
    },

 

創建測距提示的方法createMeasureTooltip

    //創建一個新的測距提示
    createMeasureTooltip() {
      let self = this;
      //如果已經存在幫助提示框則移除
      if (self.measureTooltipElement) {
        self.measureTooltipElement.parentNode.removeChild(
          self.measureTooltipElement
        );
      }
      //創建幫助提示要素的div
      self.measureTooltipElement = document.createElement("div");
      //設置幫助提示要素的樣式
      self.measureTooltipElement.className = "ol-tooltip ol-tooltip-measure";
      //創建一個幫助提示的覆蓋標注
      self.measureTooltip = new Overlay({
        element: self.measureTooltipElement,
        offset: [0, -15],
        positioning: "bottom-center",
      });
      //將幫助提示的覆蓋標注添加到地圖中
      self.map.addOverlay(self.measureTooltip);
    },

其中又用到測量距離的方法formatLength

    // 測量距離
    formatLength(line) {
      //計算平面距離
      var length = getLength(line);
      //定義輸出變量
      var output;
      //如果長度大於1000,則使用km單位,否則使用m單位
      if (length > 1000) {
        output = Math.round((length / 1000) * 100) / 100 + " " + "km";
      } else {
        output = Math.round(length * 100) / 100 + " " + "m";
      }
      return output;
    },

6、取消測距方法的點擊事件

    // 取消測距
    cancleCalDistance() {
      let self = this;
      this.map.removeInteraction(this.draw);
      this.lineSource.clear();
      let layerArr = this.map.getOverlays();
      var deleteOverlayArr = [];
      layerArr.forEach((item) => {
        if (
          item.values_.element.className ===
          "ol-tooltip ol-tooltip-static draw_km"
        ) {
          deleteOverlayArr.push(item);
        }
      });
      deleteOverlayArr.forEach((item) => {
        self.map.removeOverlay(item);
      });
    },

7、完整示例代碼

<template>
  <div>
    <div>
      <el-button type="primary" @click="beginCalDistance">開始測距</el-button>
      <el-button type="primary" @click="cancleCalDistance">取消測距</el-button>
    </div>
    <div id="app">
      <div id="map" class="map"></div>
    </div>
  </div>
</template>

<script>
//導入基本模塊
import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import { Fill, Style, Stroke } from "ol/style";
//導入相關模塊
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { TileWMS, Vector as VectorSource } from "ol/source";
import { Select, Draw } from "ol/interaction";
import { getLength } from "ol/sphere";
import { LineString } from "ol/geom";
import Overlay from "ol/Overlay";

export default {
  name: "olMapImageWMSDrawLineAndCalDistance",
  data() {
    return {
      map: null, // map地圖
      layer: null, //地圖圖層
      lineLayer: null, //線圖層
      draw: null,
      lineSource: null,
      coordinate: [],
      measureTooltipElement: null,
      measureTooltip: null,
      sketch: null,
      geom: null,
    };
  },
  mounted() {
    this.initMap();
  },
  methods: {

    //開始測距
    beginCalDistance() {
      //調用繪圖工具並傳遞類型為線,其他類型有Point,LineString,Polygon,Circle
      this.onAddInteraction("LineString");
      //創建一個新的測距提示
      this.createMeasureTooltip();
    },

    // 取消測距
    cancleCalDistance() {
      let self = this;
      this.map.removeInteraction(this.draw);
      this.lineSource.clear();
      let layerArr = this.map.getOverlays();
      var deleteOverlayArr = [];
      layerArr.forEach((item) => {
        if (
          item.values_.element.className ===
          "ol-tooltip ol-tooltip-static draw_km"
        ) {
          deleteOverlayArr.push(item);
        }
      });
      deleteOverlayArr.forEach((item) => {
        self.map.removeOverlay(item);
      });
    },
    // 繪圖工具
    onAddInteraction(type) {
      let self = this;
      //勾繪矢量圖形的類
      this.draw = new Draw({
        //source代表勾繪的要素屬於的數據集
        source: self.lineSource,
        //type 表示勾繪的要素包含的 geometry 類型
        type: type,
      });

      //繪制開始時觸發的事件
      this.draw.on("drawstart", function (evt) {
        self.sketch = evt.feature;
        //提示框的坐標
        var tooltipCoord = evt.coordinate;
        //定義一個事件監聽,監聽幾何要素的change事件
        var listener = self.sketch.getGeometry().on("change", function (evt) {
          //獲取繪制的幾何對象
          self.geom = evt.target;
          //定義一個輸出對象,用於記錄長度
          var output;
          //判斷交互類型是否為線
          if (self.geom instanceof LineString) {
            //輸出多線段的長度
            output = self.formatLength(self.geom);
            //獲取多線段的最后一個點的坐標
            tooltipCoord = self.geom.getLastCoordinate();
          }
          //設置測量提示框的內標簽為最終輸出結果
          self.measureTooltipElement.innerHTML = output;
          self.measureTooltipElement.className =
            "ol-tooltip ol-tooltip-static draw_km";
          //設置測量提示框的位置坐標
          self.measureTooltip.setPosition(tooltipCoord);
        });
      });

      //繪制結束時觸發的事件
      this.draw.on("drawend", function (e) {
        //輸出坐標信息
        const geometry = e.feature.getGeometry();
        let pointArr = geometry.getCoordinates();
        self.coordinate.push(pointArr);
        console.log("self.coordinate=" + self.coordinate);
        //移除交互
        self.removeDraw();
      });

      //添加交互
      self.map.addInteraction(this.draw);
    },

    //刪除交互
    removeDraw() {
      this.map.removeInteraction(this.draw);
    },

    //創建一個新的測距提示
    createMeasureTooltip() {
      let self = this;
      //如果已經存在幫助提示框則移除
      if (self.measureTooltipElement) {
        self.measureTooltipElement.parentNode.removeChild(
          self.measureTooltipElement
        );
      }
      //創建幫助提示要素的div
      self.measureTooltipElement = document.createElement("div");
      //設置幫助提示要素的樣式
      self.measureTooltipElement.className = "ol-tooltip ol-tooltip-measure";
      //創建一個幫助提示的覆蓋標注
      self.measureTooltip = new Overlay({
        element: self.measureTooltipElement,
        offset: [0, -15],
        positioning: "bottom-center",
      });
      //將幫助提示的覆蓋標注添加到地圖中
      self.map.addOverlay(self.measureTooltip);
    },

    //初始化地圖
    initMap() {
      //地圖圖層
      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.lineSource = new VectorSource({ wrapX: false });
      this.lineLayer = new VectorLayer({
        source: this.lineSource,
      });

      this.map = new Map({
        //地圖容器ID
        target: "map",
        //引入地圖
        layers: [this.layer, this.lineLayer],
        view: new View({
          //地圖中心點
          center: [987777.93778, 213834.81024],
          zoom: 14,
          minZoom: 6, // 地圖縮放最小級別
          maxZoom: 19,
        }),
      });
    },
   
    // 測量距離
    formatLength(line) {
      //計算平面距離
      var length = getLength(line);
      //定義輸出變量
      var output;
      //如果長度大於1000,則使用km單位,否則使用m單位
      if (length > 1000) {
        output = Math.round((length / 1000) * 100) / 100 + " " + "km";
      } else {
        output = Math.round(length * 100) / 100 + " " + "m";
      }
      return output;
    },
  },
};
</script>

<style scoped>
.map {
  width: 100%;
  height: 800px;
}
</style>

 


免責聲明!

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



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