
官网demo地址:
Draw Features
先初始化地图,准备一个空的矢量图层,用于显示绘制的图形。
initLayers() {
      const raster = new TileLayer({
        source: new XYZ({
          url: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
        }),
      });
      const source = new VectorSource({ wrapX: false });
      this.vectorlayer = new VectorLayer({
        source: source,
      });
      this.map = new Map({
        layers: [raster, this.vectorlayer],
        target: "map",
        view: new View({
          center: [-11000000, 4600000],
          zoom: 4,
        }),
      });
    }, 想要在地图上绘制图形,需要用到一个交互类Draw,new Draw,设置绘制的图形类型。常见类型包括 'Point', 'LineString', 'Polygon', 'Circle', 'MultiPoint', 'MultiLineString', 'MultiPolygon'。
addDrawInteraction() {
      this.draw = new Draw({
        source: this.vectorlayer.getSource(),
        type: this.type,
      });
      this.map.addInteraction(this.draw);
    },Draw还有些常用参数
-  clickTolerance:- 类型: number
- 描述: 指定绘制时允许的点击距离容差(以像素为单位)。这是为了允许用户在移动鼠标时具有一定的容差,以便更容易地点击绘制。
- 默认值: 6
 
- 类型: 
-  features:- 类型: ol.Collection<ol.Feature>
- 描述: 一个 Collection实例,用于存储绘制的特征。如果指定了此属性,绘制的特征将添加到该集合中。
 
- 类型: 
-  source:- 类型: ol.source.Vector
- 描述: 一个 VectorSource实例,用于存储绘制的特征。如果没有指定features,绘制的特征将添加到此数据源中。
 
- 类型: 
-  dragVertexDelay:- 类型: number
- 描述: 指定绘制顶点时拖动操作的延迟时间(以毫秒为单位)。
- 默认值: 500
 
- 类型: 
-  snapTolerance:- 类型: number
- 描述: 指定绘制时顶点的捕捉容差(以像素为单位)。这是为了使用户更容易将新顶点捕捉到现有顶点上。
- 默认值: 12
 
- 类型: 
-  stopClick:- 类型: boolean
- 描述: 是否停止点击事件。设置为 true时,绘制交互将停止触发地图的点击事件。
- 默认值: false
 
- 类型: 
-  maxPoints:- 类型: number
- 描述: 绘制的最大顶点数。对于线和多边形,这个值可以限制绘制的顶点数量。
- 默认值: Infinity
 
- 类型: 
-  minPoints:- 类型: number
- 描述: 绘制的最小顶点数。例如,对于多边形,至少需要三个顶点来形成一个闭合的形状。
- 默认值: 2
 
- 类型: 
-  style:- 类型: ol.style.Style或Array<ol.style.Style>或ol.StyleFunction
- 描述: 指定绘制过程中几何图形的样式。可以是一个样式实例、样式实例数组或一个样式函数。
 
- 类型: 
-  geometryFunction:- 类型: function
- 描述: 自定义几何生成函数,用于在绘制时生成几何图形。该函数接收两个参数:coordinates(当前坐标数组)和geometry(当前几何图形)。
 
- 类型: 
下拉框切换时需要先移除之前的Draw,再实例化一个新的Draw添加到地图上。
  changeDrawType() {
      this.map.removeInteraction(this.draw);
      this.addDrawInteraction();
    },使用removeLastPoint方法可以撤回最后绘制的一个点。

document.getElementById("undo").addEventListener("click",  ()=> {
      this.draw.removeLastPoint();
    });一般来说,在地图上绘制完图形肯定要拿到图形数据上传或者做其他的操作,我们来看看怎么获取数据。
方法一:直接从vectorlayer图层上获取
this.vectorlayer.getSource().getFeatures()方法二:使用Draw的参数features绑定数组
let featureArr = new Collection();
this.draw = new Draw({
    features: featureArr,
});features绑定的数组不是普通的数组,Collection是openlayers内部定义的一个类似数组的集合。它拥有一些跟数组类似的方法。具体介绍和方法可以参考官网文档:
OpenLayers v9.2.4 API - Class: Collection
如果获取数据的时机是绘制完成之后点击按钮后获取,那两种方式没什么区别。但若是希望绘制完成后马上获取,使用this.vectorlayer.getSource().getFeatures()就会有一点小问题。。。
 this.draw.on("drawend", (e) => {
        console.log("draw", e.feature);
        console.log("获取数据:", this.vectorlayer.getSource().getFeatures());
  });
已经绘制了一个图形,但是并没有获取到 。this.vectorlayer.getSource().getFeatures()不能实时获取到绘制图形的数据,因为drawend事件里feature还没被加到图层上。
但,也不是没有解决办法,变成异步就可以。
setTimeout(() => {
    console.log("获取数据:", this.vectorlayer.getSource().getFeatures());
});而使用Draw的features参数绑定Collection就不会有这个问题。
this.draw.on("drawend", (e) => {
        console.log("draw", e.feature);
        console.log("featureArr", this.featureArr);
  });
总的来说,两种方法都可以,甚至可以定义一个数组,每次绘制完都push一下当前绘制的feature。 具体怎么使用看业务需求喽。
完整代码:
<template>
  <div class="box">
    <h1>Draw Features绘制图形</h1>
    <div id="map"></div>
    <div class="row">
      <div class="col-auto">
        <span class="input-group">
          <label class="input-group-text" for="type">Geometry type:</label>
          <select
            class="form-select"
            id="type"
            @change="changeDrawType"
            v-model="type"
          >
            <option value="Point">Point</option>
            <option value="LineString">LineString</option>
            <option value="Polygon">Polygon</option>
            <option value="Circle">Circle</option>
            <option value="None">None</option>
          </select>
          <input class="form-control" type="button" value="Undo" id="undo" />
        </span>
        <el-button type="primary" @click="getDrawFeatures">获取</el-button>
      </div>
    </div>
  </div>
</template>
 
<script>
import Draw from "ol/interaction/Draw.js";
import { createBox } from "ol/interaction/Draw";
import Map from "ol/Map.js";
import View from "ol/View.js";
import { OSM, Vector as VectorSource } from "ol/source.js";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer.js";
import XYZ from "ol/source/XYZ";
import Feature from "ol/Feature.js";
import Polygon from "ol/geom/Polygon.js";
import Point from "ol/geom/Point.js";
import { Collection } from "ol";
export default {
  data() {
    return {
      map: null,
      vectorlayer: null,
      type: "Point",
      draw: null,
      featureArr: new Collection(),
    };
  },
  methods: {
    getDrawFeatures() {
      console.log("方法一", this.vectorlayer.getSource().getFeatures());
      console.log("方法二", this.featureArr);
    },
    changeDrawType() {
      this.map.removeInteraction(this.draw);
      this.addDrawInteraction();
    },
    initLayers() {
      const raster = new TileLayer({
        source: new XYZ({
          url: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
        }),
      });
      const source = new VectorSource({ wrapX: false });
      this.vectorlayer = new VectorLayer({
        source: source,
      });
      this.map = new Map({
        layers: [raster, this.vectorlayer],
        target: "map",
        view: new View({
          center: [-11000000, 4600000],
          zoom: 4,
        }),
      });
    },
    addDrawInteraction() {
      this.draw = new Draw({
        source: this.vectorlayer.getSource(),
        type: this.type,
        features: this.featureArr,
        //freehand: true, //是否启用自由绘制模式
      });
      this.map.addInteraction(this.draw);
      this.draw.on("drawend", (e) => {
        console.log("draw", e.feature);
        // console.log("获取数据:", this.vectorlayer.getSource().getFeatures());
        console.log("featureArr", this.featureArr);
        // setTimeout(() => {
        //   console.log("source", this.vectorlayer.getSource().getFeatures());
        // });
      });
    },
  },
  mounted() {
    this.initLayers();
    this.addDrawInteraction();
    document.getElementById("undo").addEventListener("click", () => {
      this.draw.removeLastPoint();
    });
  },
};
</script>
<style scoped>
#map {
  width: 100%;
  height: 500px;
}
.box {
  height: 100%;
}
</style>



















