官网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>