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 {
   100%;
  height: 800px;
}
</style>
原文地址:https://www.cnblogs.com/badaoliumangqizhi/p/15748161.html