小白一枚,只是单纯纪录,不喜勿喷,希望能帮到刚入门的大家
//新建点线面图层
addDrawLayer() {
this.draw_vector = new VectorLayer({
source: this.draw_source,
title: '自由图层绘制点线面',
name: 'operateTu',
visible: true,
zIndex: 99999,
//绘制好后,在地图上呈现的样式
style: new Style({
fill: new Fill({
color: "rgba(255, 255, 255, 0.2)",
}),
stroke: new Stroke({
//边界样式
color: "#ffcc33",
width: 3,
}),
//点样式继承image
image: new Icon({
src: require('@/assets/index/dingwei-tu.png'),
//大小
scale: 1,
}),
}),
});
console.log(this.draw_vector,222222222)
this.map.addLayer(this.draw_vector);
},
先创建点线面图层,并添加到地图容器中
//html: 判断选择要绘制的图形
<div class="operate" v-show="showType">
<!-- <div style="background-color: #235298; color: white; height: 40px; line-height: 40px;cursor: default;">
<i class="el-icon-edit"></i> 绘制
</div> -->
<div @click="openSelectCategory('Point')">
<span class="el-icon-location-information"></span>
<span style="font-size: 18px;">点</span>
</div>
<div @click="openSelectCategory('LineString')">
<span class="el-icon-share"></span>
<span style="font-size: 18px;">线</span>
</div>
<div @click="openSelectCategory('Polygon')">
<span class="el-icon-reading"></span>
<span style="font-size: 18px;">面</span>
</div>
</div>
openSelectCategory(type) {
//图层名称填写弹框显示隐藏
this.dialogVisible = true;
this.type = type
},
//我是在点击选择要绘制的图形后又添加了一个图层名称填写弹框
html:
<!-- 选择类型的弹框 -->
<el-dialog
title="操作"
:visible.sync="dialogVisible"
width="30%"
append-to-body
:before-close="handleClose">
<el-row :gutter="6">
<el-form :model="formData" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="图层名称" prop="layer">
<el-input v-model="formData.layer"></el-input>
</el-form-item>
</el-form>
</el-row>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="submitForm()">确 定</el-button>
</span>
</el-dialog>
点击确定后隐藏弹框开始绘制
// 提交表单并开始绘制点线面
submitForm() {
this.$refs.ruleForm.validate((valid) => {
if (valid) {
this.dialogVisible = false;
this.addDrawLayer();
}
// this.map.removeInteraction(this.draw);
// 绘制层
this.draw = new Draw({
source: this.draw_source,
type: this.type,
//绘制时,在地图上呈现的样式
style: new Style({
fill: new Fill({
color: "rgba(255, 255, 255, 0.2)",
}),
stroke: new Stroke({
color: "rgba(38,126,255,0.7)",
width: 6,
}),
image: new Circle({
radius: 7,
fill: new Fill({
color: "#ffcc33",
}),
}),
}),
});
// 结束时触发的事件
this.draw.on("drawend", (e) => {
// //绘制完成后的坐标数组
this.geometry = e.feature.getGeometry().getCoordinates();
this.feature = e.feature;
// 经过wkt 处理过的值
// console.log(this.feature,'要素');
var strwkt = new WKT().writeFeature(e.feature, {
dataProjection: "EPSG:4326",//目标坐标系
featureProjection: "EPSG:4326" //当前坐标系
});
console.log(strwkt,'wkt');
//............处理格式用的可省略
//处理wkt格式数据
let index = strwkt.indexOf('(') + 1; // 获取第一个左括号的索引,加 1 后就是第一个数值的位置
let subString = strwkt.substring(index, strwkt.length - 1); // 获取括号内的子字符串
let newString = '(' + subString + ')'; // 在两端添加一个额外的括号
this.formData.coords = 'MULTI' + strwkt.replace(subString, newString);
// // POLYGON 面
// // LINESTRING 线
// // POINT 点
if (strwkt.includes('POINT')) {
this.formData.coordsType = '1';
} else if (strwkt.includes('LINESTRING')) {
this.formData.coordsType = '2';
} else {
this.formData.coordsType = '3';
}
//............处理格式用的可省略
// 创建Overlay 覆盖物弹窗
//获取popupDOM
let elPopup = this.$refs.popup;
this.popup = new Overlay({
//要添加到覆盖物元素
element: elPopup,
//在地图所在的坐标系框架下,overlay 放置的位置。
positioning: "bottom-center",
//是否应停止事件传播到地图视口
stopEvent: false,
//偏移量,像素为单位
offset: [0, 10],
});
this.map.addOverlay(this.popup);
// 控制弹窗显示与隐藏的元素
this.popupShow = true
// 设置弹窗位置
if (e.feature.getGeometry().getCoordinates()[0] instanceof Array && e.feature.getGeometry().getCoordinates().length != 1) {
this.popup.setPosition(e.feature.getGeometry().getCoordinates()[e.feature.getGeometry().getCoordinates().length - 1]);
} else if (e.feature.getGeometry().getCoordinates().length == 1 && e.feature.getGeometry().getCoordinates()[0] instanceof Array) {
this.popup.setPosition(e.feature.getGeometry().getCoordinates()[0][e.feature.getGeometry().getCoordinates()[0].length - 2]);
}
else {
this.popup.setPosition(e.feature.getGeometry().getCoordinates());
}
this.map.removeInteraction(this.draw); //移除交互
})
//添加绘制交互
this.map.addInteraction(this.draw);
});
},
Overlay详情可看 OpenLayers - Overlay简介
他添加了一个弹窗
<!-- 新增或者取消编辑的弹框 -->
<div ref="popup" class="popup" v-show = "popupShow">
<div class = "popup-header">
<span>{{ popupTitle }}</span>
<img src = "../../../assets/index/guanbi-big.png" class = "hand" @click = "() => {
//关闭提示图层
popup.setPosition(null);
popupShow = false;
//开启点编辑图层
pointPopupShow = true;
//开启编辑功能
editorFeature(true);
editModel = true;
}"/>
</div>
<div class = "popup-content" v-html="popupContent"></div>
<div class = "popup-footer" style=" margin-top: -30px;">
<el-button type="primary" @click = "openAddStreet">提交</el-button>
<el-button @click.stop = "clearDraw()">取消</el-button>
</div>
点击取消就清除点击右上关闭就可以对创建的元素进行编辑
editorFeature(flag) {
// console.log(flag)
if (this.editModel) return;
// this.editModel = true;
this.editModel = flag;
if (flag) {
// 要素选择组件
this.select = new Select({
wrapX: false,
});
// this.select.getFeatures().clear();
// this.select.getFeatures().array_.push(this.feature);//将要选择的要素push进去
this.select.dispatchEvent(new SelectEvent(
"select",
[
//绘制结束时的要素
this.feature
],
))
// 要素编辑
this.modify = new Modify({
features: this.select.getFeatures(),
deleteCondition: function (e) {
//单机删除点位
if (e.type == "singleclick") {
return Object(true);
}
}
});
// 编辑完成后 监听修改feature
var that = this;
this.modify.on("modifyend", function (e) {
console.log(e.features);
// geometry //绘制完成后的坐标数组
that.geometry = e.features.array_[0].getGeometry().getCoordinates();
console.log('绘制完成后的坐标数组', that.geometry );
that.returnFeature = e.features.array_[0];
// // 经过wkt 处理过的值
let strwkt = new WKT().writeFeature(e.features.array_[0], {
dataProjection: "EPSG:4326",//目标坐标系
featureProjection: "EPSG:4326" //当前坐标系
});
// 将值赋给表单数据
that.formData.coords = 'MULTI' + strwkt;
});
this.select.on("select", function (e) {
//临时的解决方法 调用两次
// that.writeOverLays();
setTimeout(function () {
that.$forceUpdate();
// that.writeOverLays();
}, 100)
});
this.map.addInteraction(this.select);
this.map.addInteraction(this.modify);
} else {
this.pointPopupShow = false;
this.map.removeInteraction(this.select);
this.map.removeInteraction(this.modify);
this.select = null;
this.modify = null;
//清理所有提示overlay
for (const popup of this.popupArray) {
this.map.removeOverlay(popup);
}
this.$forceUpdate();
}
return this.returnFeature;
},
编辑要素就是使用SelectAPI创建对象拿到要修改的图形要素(就是你绘制的图形) 然后 使用ModifyAPI编辑 使用modifyend监听修改feature 拿到修改后的坐标
// 最后提交
openAddStreet() {
// 调接口 把数据传给后台
this.popupShow = false
addLayer(this.formData).then(res => {
console.log(this.formData);
if (res.code !== 200 || res.code == null) {
// 关闭弹窗
// 清除绘制
this.clearDraw()
this.$message.error('添加失败');
this.popupShow = false
} else {
this.$bus.$emit('refash', this.refash)
this.$message({ message: '添加成功', type: 'success'})
this.popupShow = false
this.clearDraw()
}
console.log(res);
})
},
清除方法
// 清除绘制图层
clearDraw() {
this.popupShow = false
this.map.removeInteraction(this.draw); //移除交互
this.draw_vector.getSource().clear(); //清除图层上的所有要素
},
至于为什么会双击弹出弹框 在mounted中使用
var that = this;
this.$nextTick(() => {
this.map.getViewport().oncontextmenu = function (e) {
if (that.editModel) {
e.preventDefault();
//删除点
}
}
//
this.map.getViewport().ondblclick = (e) => {
if (that.editModel) {
e.preventDefault();
// 创建Overlay
let elPopup = that.$refs.popup;
that.popup = new Overlay({
element: elPopup,
positioning: "bottom-center",
stopEvent: true,
offset: [0, 10],
});
that.map.addOverlay(that.popup);
that.popupShow = true;
// 设置弹窗位置
that.popup.setPosition(that.map.getEventCoordinate(e));
}
}
})
最后附上引用api
// 引入openlayers地图组件
import "ol/ol.css";
import { Vector as VectorLayer } from "ol/layer";
import { OSM, Vector as VectorSource } from "ol/source";
import Draw from "ol/interaction/Draw";
import { Fill, Stroke, Style, Text, Circle , Icon } from "ol/style";
import Overlay from 'ol/Overlay'
import WKT from 'ol/format/WKT'
import Select, { SelectEvent } from 'ol/interaction/Select'
import Modify from 'ol/interaction/Modify'
我是小白 这都是之前copy公司大佬写好的一部分代码 有什么不足的地方可以跟我说 大家一块进步