Vue+Openlayers实现绘制线段并测量距离显示

场景

Vue+Openlayer使用Draw实现交互式绘制线段:

Vue+Openlayer使用Draw实现交互式绘制线段_BADAO_LIUMANG_QIZHI的博客-CSDN博客_vue 线段

在上面已经实现交互式绘制线段基础上,怎样实现测量距离。

注:

博客:
BADAO_LIUMANG_QIZHI的博客_霸道流氓气质_CSDN博客-C#,SpringBoot,架构之路领域博主
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

实现

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>

​

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
要在 Vue 中使用 OpenLayers 实现图层控制控件,可以按照以下步骤进行操作: 1. 安装 OpenLayersVue: ``` npm install ol vue ``` 2. 在 Vue 中引入 OpenLayers: ```javascript import ol from 'ol' import 'ol/ol.css' ``` 3. 创建地图容器: ```html <template> <div ref="map" class="map"></div> </template> ``` 4. 在 Vue 的 mounted 钩子函数中创建地图: ```javascript mounted() { // 创建地图容器 const map = new ol.Map({ target: this.$refs.map, layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ center: ol.proj.fromLonLat([116.3975, 39.9085]), zoom: 12 }) }); this.map = map; } ``` 5. 创建图层控制控件: ```html <template> <div ref="map" class="map"> <div class="ol-control ol-custom-control"> <div class="ol-custom-control-header">图层控制</div> <div class="ol-custom-control-body"> <div v-for="(layer, index) in layers" :key="index"> <input type="checkbox" :id="layer.name" v-model="layer.visible"> <label :for="layer.name">{{ layer.name }}</label> </div> </div> </div> </div> </template> ``` 6. 在 Vue 的 data 中定义图层数据和控件的状态: ```javascript data() { return { map: null, layers: [ { name: 'OSM', visible: true, layer: new ol.layer.Tile({ source: new ol.source.OSM() }) }, { name: 'Bing Maps', visible: false, layer: new ol.layer.Tile({ source: new ol.source.BingMaps({ key: 'your-bingmaps-api-key', imagerySet: 'Road' }) }) } ] } } ``` 7. 在 Vue 的 watch 中监听图层状态的变化并更新地图: ```javascript watch: { layers: { deep: true, handler(layers) { const map = this.map; map.getLayers().clear(); layers.forEach(layer => { if (layer.visible) { map.addLayer(layer.layer); } }); } } } ``` 通过以上步骤就可以在 Vue实现图层控制控件了。需要注意的是,在实际应用中,可以根据需要自定义控件的样式和布局。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霸道流氓气质

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值