实现在openlayer中绘制多边形,编辑,删除等

开发环境:"ol": "^6.5.0", "vue": "^2.6.12",  。node版本:14.18.3

1.将绘制的代码封装成类,olDrawTool.js

import { Feature } from "ol";
import * as olExtent from "ol/extent";
import { GeoJSON } from "ol/format";
import Overlay from "ol/Overlay";
import { Vector as VectorSource } from "ol/source";
import { Vector as VectorLayer } from "ol/layer";
import { Stroke, Style } from "ol/style";
import { Draw, Modify, Snap } from "ol/interaction";

/**
 * 绘制多边形工具
 * @param {Object} map 地图实例对象
 * @param {Object} options 需要的参数
 */
class olDrawTool{
  constructor(map, options) {
    this.map = map; //地图实例
    this.options = options || {};
    this.initData();
  }
  initData() {
    this.drawInteraction = null; //绘制图层对象
    this.clickHandler = null; //绘制图层对象
    this.drawLayers = []; //绘制图层集合
    this.delLayers = []; //删除图层的图标
  }
  //开始绘制
  /**
   *
   * @param {Function} drawendFun 绘制结束事件
   */
  startDraw(drawendFun) {
    const type = this.options.type || "Polygon";
    //实例化一个矢量图层Vector作为绘制层
    let vector = new VectorLayer({
      source: new VectorSource({ wrapX: false }),
      style: this.options.style || this.layerStyle(),
    });

    this.drawInteraction = new Draw({
      source: vector.getSource(),
      type: type,
      geometryFunction: this.options.geometryFunction,
    });
    this.map.addLayer(vector);

    //绘制结束
    this.drawInteraction.on("drawend", (event) => {
      const feature = event.feature;
      this.drawLayers.push(vector);
      drawendFun && drawendFun(this.drawLayers);
      //这里绘制图形结束需要先关闭绘制功能,再打开,保证每个图形独立
      this.map.removeInteraction(this.drawInteraction);
      this.drawInteraction = null;
      this.startDraw(drawendFun);
    });
    this.map.addInteraction(this.drawInteraction);
  }
  //编辑所有图层
  editLayer() {
    // 先取消绘制图形控件
    this.drawInteraction.setActive(false);
    this.drawLayers.forEach((layer) => {
      const modify = new Modify({ source: layer.getSource() });
      this.map.addInteraction(modify);
      let snap = new Snap({ source: layer.getSource() });
      this.map.addInteraction(snap);
    });
  }
  //完成图层编辑
  editLayerEnd() {
    this.drawInteraction.setActive(true);
    // 移除Modify和Snap交互
    let ModifyArr = this.map
      .getInteractions()
      .getArray()
      .filter(
        (interaction) =>
          interaction instanceof Modify || interaction instanceof Snap
      );
    ModifyArr.forEach((item) => this.map.removeInteraction(item));
  }
  //撤销
  revokeDraw() {
    if (this.drawInteraction) {
      this.drawInteraction.removeLastPoint();
    }
  }

  // 创建样式
  createDeleteButton(src, layer, delCallback) {
    let deleteButton = document.createElement("div");
    let img = document.createElement("img");
    img.style.width = "22px";
    img.style.height = "22px";
    img.style.transform = "translate(-50%, -100%)";
    img.src = src;
    deleteButton.appendChild(img);

    // 点击删除按钮时,删除对应的 VectorLayer(图层)和 ‘删除图标’
    deleteButton.addEventListener("click", () => {
      this.map.removeLayer(layer);
      const overlay = this.delLayers.find(
        (ov) => ov.get("layerid") === layer.ol_uid
      );
      if (overlay) {
        this.map.removeOverlay(overlay);
        this.delLayers.splice(this.delLayers.indexOf(overlay), 1);
      }

      let index = this.drawLayers.indexOf(layer);
      if (index != -1) this.drawLayers.splice(index, 1);
      delCallback && delCallback(layer, this.drawLayers);
    });
    return deleteButton;
  }
  /**
   * @param {String} delIcon assets/images路径下的图片
   * @param {Function} delCallback 删除结束回调函数
   */
  //删除图层
  delDraw(delCallback,delIcon) {
    if(!delIcon){
      delIcon = require("../../../assets/images/del.png");
    }
    this.drawInteraction.setActive(false);
    this.drawLayers.forEach((layer) => {
      const deleteButton = this.createDeleteButton(delIcon, layer, delCallback);
      const deleteOverlay = new Overlay({
        element: deleteButton,
        position: [0, 0], // 这里先随便设置一个位置,后面再根据 layer 更新它的位置
      });
      deleteOverlay.set("layerid", layer.ol_uid); // 将对应的 VectorLayer的ol_uid 存储在 Overlay 对象中
      const extent = layer.getSource().getExtent();
      const center = olExtent.getCenter(extent);
      deleteOverlay.setPosition(center);

      this.delLayers.push(deleteOverlay);
      this.map.addOverlay(deleteOverlay);
    });

  }
  //完成删除
  delDrawEnd() {
    this.drawInteraction.setActive(true);
    this.delLayers.forEach((item) => {
      this.map.removeOverlay(item);
    });
    this.delLayers = [];
  }
  //清除绘制的图形,事件等
  clear() {
    this.drawLayers.forEach((item) => this.map.removeLayer(item));
    this.delLayers.forEach((item) => this.map.removeLayer(item));
    this.editLayerEnd();
    this.map.removeInteraction(this.drawInteraction);
    this.initData();
  }
  layerStyle() {
    return new Style({
      stroke: new Stroke({
        color: "red",
        width: 3,
        lineDash: [4, 8],
      }),
    });
  }
}
export default olDrawTool;

2. 使用,ToolBarDarw.vue

<template>
<div>
    <div
        @click="startDraw"
        class="flex-dc"
      >
        <i class="el-icon-zoom-in"></i>
        <span>开始绘制</span>
      </div>
      <div
        class="flex-dc"
        @click="editLayer"
      >
        <i class="el-icon-edit-outline"></i>
        <span>{{ isEditing ? "完成" : "" }}编辑</span>
      </div>
      <div
        class="flex-dc"
        @click="revokeDraw"
      
      >
        <i class="el-icon-refresh-left"></i>
        <span>撤销</span>
      </div>
      <div class="flex-dc" @click="delDraw">
        <i class="el-icon-delete"></i>
        <span>{{ isDeling ? "完成" : "" }}删除</span>
      </div>
      <div class="flex-dc" @click="escEdit">
        <i class="el-icon-s-unfold"></i>
        <span>退出</span>
      </div>
</div>
</template>
<script>
import olDrawTool from "../js/olDrawTool";
 props: ["map"],

 data() {
    return {
      isEditing: false, //是否编辑状态
      isDeling: false, //是否删除状态
      isDrawing: true,
      DrawTool: null, //绘制工具实例
      drawLayers: [],
    };
  },
  methods: {
 // 绘制矢量图层
    drawPolygon() {
      if(!this.DrawTool){
          this.DrawTool = new olDrawTool(this.map);
      }
     
      this.DrawTool.startDraw((drawLayers) => {
        //绘制完成回调函数,根据业务决定是否需要
        this.drawLayers = drawLayers;
      });
    },
    // 撤销绘制
    revokeDraw() {
      this.DrawTool.revokeDraw();
    },
    // 删除矢量图层
    delDraw() {
      this.isDeling = !this.isDeling;
      if (this.isDeling) {
        this.isDrawing = false;
        this.DrawTool.delDraw((layer, drawLayers) => {
          console.log(drawLayers, layer, "=======删除!");
        });
      } else {
        this.isDrawing = true;
        this.DrawTool.delDrawEnd();
      }
    },
    // 编辑矢量图层
    editLayer() {
      this.isEditing = !this.isEditing;
      if (this.isEditing) {
        this.isDrawing = false;
        this.DrawTool.editLayer();
      } else {
        this.isDrawing = true;
        this.DrawTool.editLayerEnd();
      }
    },
    // 退出
    escEdit() {
      this.DrawTool.clear();
      this.isEditing = false;
      this.isDeling = false;
      this.isDrawing = true;
      this.DrawTool = null;
    },
}
</script>

到这里基本功能就可以实现了,功能上还存在细节上的问题,还需根据需求完善。

下面是点击删除时的效果。

 

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值