openlayer Vue 测绘功能

本文介绍如何在Vue项目中集成OpenLayers,并实现地图测量功能,包括距离和面积测量。文章详细展示了Vue组件的结构及如何通过交互进行地图绘制。

关于在vue上面Openlayer ,即使是官方例子,也需要一定的vue化,如下
官方例子:
https://openlayers.org/en/latest/examples/measure.html

我自己vue化之后的

<template>
  <div id="PlanMap">
    <!-- 这里是计划里面的地图页面 -->
    <div id="map" class="openLayer"></div>
    <!-- 右侧图标 -->
    <div class="control-div">
      <div><i class="iconfont icon-luru" /></div>
      <div><i class="iconfont icon-tubiao_ditu" /></div>
      <div><i class="iconfont icon-D" /></div>
      <div><i class="iconfont icon-zhinan" /></div>
      <div><i @click="updateZoom(-1)" class="el-icon-minus" /></div>
      <div><i @click="updateZoom(1)" class="el-icon-plus" /></div>
    </div>
    <!-- 中间菜单 -->
    <div id="control-center" class="control-center">
      <div
        @click="
          measureShow = !measureShow;
          mappingShow = false;
        "
        class="control-center-div"
      >
        <i class="iconfont icon-celiang" /> 测量
      </div>
      <div
        @click="
          mappingShow = !mappingShow;
          measureShow = false;
        "
        class="control-center-div"
      >
        <i class="iconfont icon-cehui" /> 测绘
      </div>
      <div class="control-center-div">
        <i class="iconfont icon-tuceng" /> 图层管理
      </div>
      <transition name="fade">
        <div v-if="measureShow" class="contorl-measure">
          <span @click="beginDraw('LineString')">距离测量</span> <br />
          <span @click="beginDraw('Polygon')">面积测量</span> <br />
          <span @click="stopDraw">结束测量</span>
        </div>
      </transition>

      <transition name="fade">
        <div v-if="mappingShow" class="contorl-mapping">
          <span>标点</span> <br />
          <span>标线</span> <br />
          <span>标面</span> <br />
          <span>结束</span>
        </div>
      </transition>
    </div>
  </div>
</template>
<script>
import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import { fromLonLat } from "ol/proj";
import { Control, defaults } from "ol/control";

import Draw from "ol/interaction/Draw";
import Overlay from "ol/Overlay";
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";

export default {
  name: "PlanMap",
  data() {
    return {
      mappingShow: false,
      measureShow: false,
      //测绘用的
      helpTooltipElement: null,
      helpTooltip: null,
      map: null,
      sketch: null,
      measureTooltipElement: null,
      measureTooltip: null,
      continueLineMsg: "单击以继续绘制线",
      continuePolygonMsg: "单击以继续绘制多边形",
      listener: null,
      drawType: "LineString",
      draw: null,
      helpMsg: "点击开始绘画",
      drawStop: false,
    };
  },
  mounted() {
    this.initLocalMap();
  },
  methods: {
    initLocalMap() {
      //获取中心点
      // // 创建控件 中间菜单的组件
      var RotateNorthControl = /*@__PURE__*/ (function (Control) {
        function RotateNorthControl(opt_options) {
          var options = opt_options || {};
          var controlCenter = document.getElementById("control-center");
          Control.call(this, {
            element: controlCenter,
            target: options.target,
          });
        }
        if (Control) RotateNorthControl.__proto__ = Control;
        RotateNorthControl.prototype = Object.create(
          Control && Control.prototype
        );
        return RotateNorthControl;
      })(Control);
      //添加自定义控件

      // 中心点
      var center = fromLonLat([108.969878, 34.298661]);
      this.map = new Map({
        layers: [
          new TileLayer({
            source: new OSM(),
          }),
        ],
        controls: defaults({
          //清除地图上默认样式(放大、缩小、旋转按钮等)
          attribution: false,
          rotate: false,
          zoom: false,
        }),
        target: "map",
        view: new View({
          center: center,
          zoom: 4,
          minZoom: 4,
          maxZoom: 18,
        }),
      });
      this.map.getControls().extend([new RotateNorthControl()]);
    },
    stopDraw() {
      //停止绘画
      this.map.removeInteraction(this.draw);
      this.drawStop = true;
      this.helpTooltipElement.classList.add("hidden");
    },
    beginDraw(type) {
      this.map.removeInteraction(this.draw);
      this.drawStop = false;
      //开始测绘处理
      var source = new VectorSource();
      // 绘制的画布
      var vector = new VectorLayer({
        source: source,
        style: this.returnLineStyleing(),
      });
      this.map.addLayer(vector);
      // 创建鼠标提示
      this.createHelpTooltip();
      // 创建绘制距离提示
      this.createMeasureTooltip();
      var _this = this;
      this.map.on("pointermove", this.pointerMoveHandler);
      //数据移出之后移出button标签
      this.map.getViewport().addEventListener("mouseout", function () {
        _this.helpTooltipElement.classList.add("hidden");
      });
      // 构建绘制方法
      this.draw = new Draw({
        source: source,
        type: type,
        style: this.returnLineStyle(),
      });
      this.map.addInteraction(this.draw);
      // 绘画开始事件
      this.draw.on("drawstart", function (evt) {
        _this.drawstartStrat(evt);
      });
      // 绘画结束事件
      this.draw.on("drawend", function () {
        _this.drawendEnd();
      });
    },
    drawstartStrat(evt) {
      //绘画开始事件
      this.sketch = evt.feature;
      var tooltipCoord = evt.coordinate;
      var _this = this;
      this.listener = this.sketch.getGeometry().on("change", function (evt) {
        var geom = evt.target;
        var output;
        if (geom instanceof Polygon) {
          output = _this.formatArea(geom);
          tooltipCoord = geom.getInteriorPoint().getCoordinates();
        } else if (geom instanceof LineString) {
          output = _this.formatLength(geom);
          tooltipCoord = geom.getLastCoordinate();
        }
        _this.measureTooltipElement.innerHTML = output;
        _this.measureTooltip.setPosition(tooltipCoord);
      });
    },
    drawendEnd() {
      //绘画结束事件
      this.measureTooltipElement.className = "ol-tooltip ol-tooltip-static";
      this.measureTooltip.setOffset([0, -7]);
      this.sketch = null;
      this.measureTooltipElement = null;
      this.createMeasureTooltip();
      unByKey(this.listener);
    },
    updateZoom(number) {
      //修改地图级别
      var view = this.map.getView();
      var zoom = view.getZoom();
      view.setZoom(zoom + number);
    },
    distanceMeasurement() {
      //距离测量
    },
    returnLineStyleing() {
      //绘制中的样式
      return new Style({
        fill: new Fill({
          color: "rgba(255, 255, 255, 0.2)",
        }),
        stroke: new Stroke({
          color: "#ffcc33",
          width: 2,
        }),
        image: new CircleStyle({
          radius: 7,
          fill: new Fill({
            color: "#ffcc33",
          }),
        }),
      });
    },
    returnLineStyle() {
      //绘制结束后的样式
      return 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: 2,
        }),
        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)",
          }),
        }),
      });
    },
    pointerMoveHandler(evt) {
      if (this.drawStop) {
        return;
      }
      // 讲初始绘画提示 绑定在鼠标上 鼠标移动跟着走
      if (evt.dragging) {
        //这个是判断是否拖拽的
        return;
      }
      /** @type {string} */ {
      }
      var helpMsg = this.helpMsg;
      if (this.sketch) {
        var geom = this.sketch.getGeometry();
        if (geom instanceof Polygon) {
          helpMsg = this.continuePolygonMsg;
        } else if (geom instanceof LineString) {
          helpMsg = this.continueLineMsg;
        }
      }
      this.helpTooltipElement.innerHTML = helpMsg;
      this.helpTooltip.setPosition(evt.coordinate);
      this.helpTooltipElement.classList.remove("hidden");
    },
    createHelpTooltip() {
      //  创建初始绘画提示  就是跟着鼠标走的那个提示DIV
      if (this.helpTooltipElement) {
        this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement);
      }
      this.helpTooltipElement = document.createElement("div");
      this.helpTooltipElement.className = "ol-tooltip hidden";
      this.helpTooltip = new Overlay({
        element: this.helpTooltipElement,
        offset: [15, 0],
        positioning: "center-left",
      });
      console.log(this.helpTooltipElement);
      this.map.addOverlay(this.helpTooltip);
    },
    createMeasureTooltip() {
      //从创建文字提示书 就是多少千米
      if (this.measureTooltipElement) {
        this.measureTooltipElement.parentNode.removeChild(
          this.measureTooltipElement
        );
      }
      this.measureTooltipElement = document.createElement("div");
      this.measureTooltipElement.className = "ol-tooltip ol-tooltip-measure";
      this.measureTooltip = new Overlay({
        element: this.measureTooltipElement,
        offset: [0, -15],
        positioning: "bottom-center",
      });
      this.map.addOverlay(this.measureTooltip);
    },
    formatLength(line) {
      //格式化长度
      var length = getLength(line);
      var output;
      if (length > 100) {
        output = Math.round((length / 1000) * 100) / 100 + " " + "km";
      } else {
        output = Math.round(length * 100) / 100 + " " + "m";
      }
      return output;
    },
    formatArea(polygon) {
      // 格式化面积
      var area = getArea(polygon);
      var output;
      if (area > 10000) {
        output =
          Math.round((area / 1000000) * 100) / 100 + " " + "km<sup>2</sup>";
      } else {
        output = Math.round(area * 100) / 100 + " " + "m<sup>2</sup>";
      }
      return output;
    },
  },
};
</script>

<style lang="scss"  >
//  不能加scoped 因为这样ol添加的样式就不能用了
.openLayer {
  width: 100%;
  height: 100%;
}
.control-div {
  position: fixed;
  top: 61px;
  right: 7px;
  width: 30px;
  height: auto;
}

.control-div div {
  color: #666666;
  width: 28px;
  height: 28px;
  background: #ffffff;
  // box-shadow: 0px 4px 9px 0px rgb(0 0 0 / 8%);
  border-radius: 2px;
  margin-top: 7px;
  cursor: pointer;
}

.control-div i {
  font-size: 18px;
  float: left;
  margin-top: 5px;
  margin-left: 6px;
}
.control-center {
  width: 240px;
  height: 36px;
  text-align: center;
  background: #ffffff;
  border: 1px solid #dedede;

  box-shadow: 0px 4px 9px 0px rgba(0, 0, 0, 0.08);
  border-radius: 6px;
  color: #666666;
  margin-left: calc(50% - 120px);
  margin-top: 10px;
}
.control-center-div {
  float: left;
  margin-top: 7px;
  margin-left: 12px;
  cursor: pointer;
}
.contorl-measure {
  box-shadow: 0px 4px 9px 0px rgba(0, 0, 0, 0.08);
  float: left;
  margin-top: 13px;
  width: 105px;
  height: 86px;
  background: #ffffff;
  border: 1px solid #dedede;
  border-radius: 6px;
}
.contorl-measure span {
  margin-top: 6px;
  float: left;
  margin-left: 20px;
  cursor: pointer;
}

.contorl-mapping {
  float: left;
  margin-top: 13px;
  margin-left: 69px;
  width: 73px;
  height: 115px;
  background: #ffffff;
  border: 1px solid #dedede;
  box-shadow: 0px 4px 9px 0px rgba(0, 0, 0, 0.08);
  border-radius: 6px;
}
.contorl-mapping span {
  margin-top: 6px;
  float: left;
  margin-left: 20px;
  cursor: pointer;
}

.fade-enter-active {
  transition: opacity 0.5s;
}
.fade-leave-active {
  transition: opacity 0s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}

.map {
  width: 100%;
  height: 400px;
}
.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;
}
.hidden {
  display: none;
}
.ol-tooltip-measure {
  opacity: 1;
  font-weight: bold;
}
.ol-tooltip-static {
  background-color: #ffcc33;
  color: black;
  border: 1px solid white;
}
.ol-tooltip-measure:before,
.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%;
}
.ol-tooltip-static:before {
  border-top-color: #ffcc33;
}
</style>>
 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值