前言
本来我是想写一个,在规定区域内绘画,并且他们之间不能那个相互交互重叠的效果,然后今天看到了一个大佬写得返回上一步的操作我觉得很好玩。so,就改成了这样,ctrl+z和ctrl+y的效果。
绘画时难免会遇到问题,撤销是一个很有用的方法。
直接上代码:
1.代码
代码如下:
<template>
<div id="map" ref="map"></div>
</template>
<script>
import "ol/ol.css";
import { Map, View } from "ol";
import OSM from "ol/source/OSM";
import Tile from "ol/layer/Tile";
import { fromLonLat } from "ol/proj";
import { Draw, Modify, Snap } from "ol/interaction";
import VectorSource from "ol/source/Vector";
import VectorLayer from "ol/layer/Vector";
import { Fill, Stroke, Style } from "ol/style";
import { FullScreen, ZoomSlider } from "ol/control";
import GeoJSON from "ol/format/GeoJSON";
// 假数据
const region = {
type: "Polygon",
coordinates: [
[
[116.33795900641341, 39.95203308766855],
[116.45448557912366, 39.95801455881917],
[116.44043996544875, 39.88420652528961],
[116.31975172942745, 39.888597335516636],
[116.33795900641341, 39.95203308766855]
]
]
};
export default {
data() {
return {
map: null,
drawed: null,
drawDataSource: null,
drawDataStyle: null,
drawDataLayers: null,
huahuaSource: [],
delHuahuaSource: []
};
},
mounted() {
this.init();
this.initRegion();
this.draw();
this.modify();
},
methods: {
// 初始化地图 start
init() {
// 初始化地图,dom,layers,view。
this.map = new Map({
target: this.$refs.map,
layers: [
new Tile({
source: new OSM()
})
],
view: new View({
zoom: 1,
center: fromLonLat([0, 0])
}),
controls: [new ZoomSlider(), new FullScreen()]
});
},
// 初始化地图 end
// 初始化区域数据 start
initRegion() {
let regionSource = new VectorSource();
let regionLayers = new VectorLayer({
source: regionSource,
style: new Style({
stroke: new Stroke({
color: "blue",
width: 3
}),
fill: new Fill({
color: "rgba(43, 213, 77, 0.1)"
})
})
});
this.map.addLayer(regionLayers);
// 一般都会是请求得到数据,我就写个假的
// 一般后端数据都是4326格式的,等得到之后将其转为3857渲染到页面上
let featrue = new GeoJSON().readFeature(region, {
dataProjection: "EPSG:4326",
featureProjection: "EPSG:3857"
});
regionSource.addFeature(featrue);
// 能够快速的定位到位置,嗯,这个很实用
this.map.getView().fit(regionSource.getExtent(), this.map.getSize());
},
// 初始化区域数据 end
// 绘画 start
draw() {
this.drawDataStyle = new Style({
stroke: new Stroke({
color: "#000000",
width: 4
}),
fill: new Fill({
color: "hotpink"
})
});
this.drawDataSource = new VectorSource();
this.drawDataLayers = new VectorLayer({
source: this.drawDataSource,
style: this.drawDataStyle
});
this.map.addLayer(this.drawDataLayers);
this.drawed = new Draw({
// 绘画的数据就放在这个图层了
source: this.drawDataSource,
// 绘画的类型是多边形 polygon
type: "Polygon",
// 停止在绘画时触发单击双击事件
stopClick: true,
// 捕捉到绘图完成的像素聚类,必须大于0
snapTolerance: 1,
// 样式
style: this.drawDataStyle
});
// 将绘画的方法添加到地图上
this.map.addInteraction(this.drawed);
// 绘画结束的事件,同理还有开始的事件
this.drawed.on("drawend", this.drawendd);
// 设置一个右键事件用来取消绘画
this.map.on("contextmenu", this.contextmenued);
// snap吸附功能 ,还有就是snap交互可以在编辑和画features时候保持拓扑结构
let snap = new Snap({
source: this.drawDataSource
});
this.map.addInteraction(snap);
},
// 绘画 end
// 绘画结束 start
drawendd(e) {
// 如果你画了,那么ctrl z y 的方法就终止,(老犯错不得行吧)
this.huahuaSource = [];
this.delHuahuaSource = [];
// 因为页面不能及时渲染所有我就加了一个nextTick,当然你也可以使用计时器,或者别的更好的方法
this.$nextTick(() => {
this.huahuaSource = this.drawDataSource.getFeatures();
});
// 监听键盘事件,vue监听挺难搞,原生YYDS
// 本来想写别的功能的,但是今天看到一个大佬的文章感觉很有趣,就加了这个方法
document.onkeydown = this.KeyboardEvents;
},
// 绘画结束 end
// Modify 修改图层
modify() {
let modify = new Modify({
source: this.drawDataSource
});
this.map.addInteraction(modify);
},
// 去除浏览器默认右击事件,并取消绘画
contextmenued(e) {
e.preventDefault();
this.drawed.abortDrawing();
},
KeyboardEvents(e) {
// 90 是z的编码 ctrlKey 即是 ctrl
if (e.keyCode == 90 && e.ctrlKey) {
this.ctrlZ();
}
// 89 是y的编码 ctrlKey 即是 ctrl
if (e.keyCode == 89 && e.ctrlKey) {
this.ctrlY();
}
},
// 返回上一步
ctrlZ() {
// length<0 还会进入,所以就改成1了
if (this.huahuaSource.length < 1) return;
let huahua_index = this.huahuaSource.length;
// delHuahuaSource 就是我下面ctrlY的数据,你不要的东西,在别人那里可能是宝贝!=-=!
this.delHuahuaSource.push(this.huahuaSource[huahua_index - 1]);
// 返回上一步那就是,移除掉你最近画的那个数据,so就是huahuaSource末尾的那个数据
this.drawDataSource.removeFeature(this.huahuaSource[huahua_index - 1]);
// 不知为啥,删了数据还存在,于是我就用splice再次删除一边,这下huahuaSource就没有数据了
this.huahuaSource.splice(huahua_index - 1, huahua_index);
},
// 都有ctrl+z那么ctrl+y也不奇怪吧
ctrlY() {
if (this.delHuahuaSource.length < 1) return;
let delHuahua_index = this.delHuahuaSource.length;
// 将ctrlZ的数据放入,huahuaSource
this.huahuaSource.push(this.delHuahuaSource[delHuahua_index - 1]);
// 然后huahuaSource的数据放入绘画图层中。
this.drawDataSource.addFeature(
this.huahuaSource[this.huahuaSource.length - 1]
);
// 同上
this.delHuahuaSource.splice(delHuahua_index - 1, delHuahua_index);
}
}
};
</script>
<style scoped>
#map {
width: 900px;
height: 400px;
margin: auto;
}
</style>