功能介绍:
1. 使用Draw进行绘画多边形
2. 点击多边形边框 使用 Modify 功能
3. 点击右键进行清除Draw功能
4. 键盘使用Ctrl+Z
对Draw和Modify添加撤回功能
// HTML:
<template>
<div id="map" ref="rootmap"></div>
</template>
<script>
import "ol/ol.css";
import { Map, View, Feature } from "ol";
import mapconfig from "./config.js";
import { Draw, Snap, Modify, DragPan } from "ol/interaction";
import { Vector as VectorSource } from "ol/source";
import { Vector as VectorLayer } from "ol/layer";
import { Circle as CircleStyle, Fill, Stroke, Style } from "ol/style";
import { MultiPoint } from "ol/geom";
export default {
data() {
return {
map: null,
sourceDraw: null,
layerDraw: null,
draw: null,
snap: null,
modify: null,
pan: null,
feature: null,
undoStack: [],
flag: false
};
},
mounted() {
var mapcontainer = this.$refs.rootmap;
this.map = new Map({
target: mapcontainer,
layers: mapconfig.layers,
view: new View({
center: mapconfig.center,
zoom: mapconfig.zoom
})
});
// 创建绘画图层
this.sourceDraw = new VectorSource();
this.layerDraw = new VectorLayer({
source: this.sourceDraw,
style: [
new Style({
fill: new Fill({
color: "rgba(225, 225, 225, .5)"
}),
stroke: new Stroke({
color: "#ff0000",
width: 3
})
}),
new Style({
image: new CircleStyle({
radius: 5,
fill: new Fill({
color: "red"
})
}),
geometry: function(feature) {
var coordinates = feature.getGeometry().getCoordinates()[0];
return new MultiPoint(coordinates);
}
})
]
});
this.map.addLayer(this.layerDraw);
// 绘画功能
this.drawFn();
// 修改功能
this.modifyFn();
this.modify.on("modifystart", this.modifyStartFn);
this.modify.on("modifyend", this.modifyEndFn);
// 吸附功能
this.snapFn();
// 地图拖动
this.panFn();
// 地图左键点击
this.map.on("click", this.mapClickFn);
// 地图右键点击
this.map.on("contextmenu", this.mapContextmenuFn);
// 地图键盘事件监听
document.onkeydown = this.mapOnkeydownFn;
},
methods: {
drawFn() {
this.draw = new Draw({
source: this.sourceDraw,
type: "Polygon",
stopClick: true,
snapTolerance: 1,
condition: function(e) {
// 按钮配置,左键点击
if (e.originalEvent.buttons === 1) {
return true;
} else {
return false;
}
}
});
this.draw.on("drawstart", this.drawStartFn);
this.draw.on("drawend", this.drawEndFn);
this.map.addInteraction(this.draw);
},
// 绘画前
drawStartFn(e) {
this.pan.setActive(false);
this.modify.setActive(false);
},
// 绘画后
drawEndFn(e) {
this.pan.setActive(true);
this.modify.setActive(true);
},
// 屏蔽绘画
removeDrawFn() {
this.draw.setActive(false);
this.map.removeInteraction(this.draw);
},
// 修改功能初始化
modifyFn() {
this.modify = new Modify({
source: this.sourceDraw,
pixelTolerance: 4
});
this.map.addInteraction(this.modify);
},
// 修改前
modifyStartFn(e) {
this.pan.setActive(false);
this.removeDrawFn();
var item = e.features.array_[0];
this.feature = new Feature();
this.feature.setGeometry(item.getGeometry().clone());
this.feature.setGeometryName(item.getGeometryName());
this.feature.setStyle(item.getStyle());
this.feature.ol_uid = item.ol_uid;
this.undoStack.push(this.feature);
},
// 修改后
modifyEndFn(e) {
this.pan.setActive(true);
setTimeout(() => {
this.removeDrawFn();
this.drawFn();
}, 200);
},
// 吸附功能
snapFn() {
this.snap = new Snap({
source: this.sourceDraw,
pixelTolerance: 4
});
},
// 地图拖动
panFn() {
this.map.getInteractions().forEach((element, index, array) => {
if (element instanceof DragPan) {
this.pan = element;
}
});
},
// 左键点击
mapClickFn(e) {
if (this.flag) {
this.removeDrawFn();
this.drawFn();
} else {
this.flag = false;
}
},
// 右键点击
mapContextmenuFn(e) {
e.preventDefault();
this.flag = true;
this.removeDrawFn();
this.pan.setActive(true);
this.modify.setActive(true);
},
// 键盘事件监听
mapOnkeydownFn(e) {
if (e.keyCode == 27) {
// ESC键盘点击,绘画清空
this.draw.abortDrawing();
} else if (e.keyCode == 90 && e.ctrlKey) {
this.draw.removeLastPoint();
if (this.undoStack.length !== 0) {
this.undoClick();
}
}
},
// 撤回上一步修改操作
undoClick() {
let feature = this.undoStack.pop();
let findFeatureByUid1 = this.findFeatureByUid(feature.ol_uid);
this.sourceDraw.removeFeature(findFeatureByUid1);
this.sourceDraw.addFeature(feature);
},
findFeatureByUid(uid) {
let featureByUid = this.sourceDraw.getFeatureByUid(uid);
return featureByUid;
}
}
};
</script>
<style scoped>
#map {
height: 100vh;
}
/*隐藏ol的一些自带元素*/
.ol-attribution,
.ol-zoom {
display: none;
}
</style>
/**
'EPSG:4326'-经纬度坐标-WGS84
'EPSG:3857'- xy坐标-web墨卡托
*/
import TileLayer from "ol/layer/Tile"
import TileGrid from "ol/tilegrid/TileGrid"
import proj4 from 'proj4'
import {register} from 'ol/proj/proj4'
import TileImage from 'ol/source/TileImage'
import { fromLonLat } from "ol/proj";
proj4.defs("EPSG:4008", "+proj=longlat +ellps=clrk66 +no_defs")
proj4.defs("BD-MC", "+proj=merc +lon_0=0 +units=m +ellps=clrk66 +no_defs")
register(proj4)
var streetmap=function(){
var baiduMapLayer=null;
// 自定义分辨率和瓦片坐标系
let resolutions = [];
let maxZoom = 18;
// 计算百度使用的分辨率
for (let i = 0; i <= maxZoom; i++) {
resolutions[i] = Math.pow(2, maxZoom - i);
}
let tilegrid = new TileGrid({
origin: [0, 0], // 设置原点坐标
resolutions: resolutions // 设置分辨率
});
// 创建百度地图的数据源
let baiduSource = new TileImage({
projection: "BD-MC",
tileGrid: tilegrid,
tileUrlFunction: function(tileCoord, pixelRatio, proj) {
let z = tileCoord[0];
let x = tileCoord[1];
let y = tileCoord[2] + 1;
// 百度瓦片服务url将负数使用M前缀来标识
if (x < 0) {
x = "M" + -x;
}
y = -y;
if (y < 0) {
y = "M" + -y;
}
let num = Math.ceil(Math.random() * 3);
return (
"http://maponline" +
num +
".bdimg.com//onlinelabel/?qt=vtile&x=" +
x +
"&y=" +
y +
"&z=" +
z +
"&styles=pl&udt=20200211&scaler=1&p=0"
);
}
});
// 百度地图层
baiduMapLayer = new TileLayer({
source: baiduSource
});
return baiduMapLayer;
}
const baiduMapLayer = streetmap();
var mapconfig = {
center: fromLonLat([116.40,40]),
zoom: 10,
layers: [baiduMapLayer],
};
export default mapconfig;