目录
一、案例截图
二、安装OpenLayers库
npm install ol
三、代码实现
代码相对来说可能会有点复杂,我已经把每行注释都写上了,这样方便大家更好去理解。
页面代码是这样的,很简单:
<div>
<el-button @click="startDrawing" :disabled="startButton" type="primary">开始绘制</el-button>
<el-button @click="endDrawing" :disabled="endButton" type="success">完成绘制</el-button>
<div id="map-container"></div>
</div>
3.1、初始化变量
关键代码:
data() {
return {
map:null,
drawing: false,
//是否禁用开始绘制按钮
startButton:false,
//是否禁用结束绘制按钮
endButton:true,
//存放当前经纬度集合
currentCoordinates: [],
//图层多边形图层级
vectorLayers: [],
// 存储虚线图层
lineLayer: null,
// 存储虚线经纬度
lineCoordinates:[],
}
},
3.2、实现一个自定义面
关键代码:
initBasePolygon() {
// 定义多边形的坐标
const coordinates = [
[
[120.430070,31.938140],
[120.428570,31.939100],
[120.429530,31.941680],
[120.431240,31.943580],
[120.432410,31.944820],
[120.433600,31.943970],
]
];
// 创建多边形对象
const polygon = new Polygon(coordinates);
// 创建特征
const polygonFeature = new Feature(polygon);
// 创建矢量图层并添加特征
const vectorSource = new VectorSource({
features: [polygonFeature]
});
const vectorLayer = new VectorLayer({
source: vectorSource,
style: new Style({
fill: new Fill({
color: 'rgba(255, 0, 0, 0.5)' // 填充颜色为红色
}),
stroke: new Stroke({
color: '#ffcc33',
width: 2
})
})
});
// 将矢量图层添加到地图中
this.map.addLayer(vectorLayer);
},
3.3、创建多边形图层
每次点击开始绘制代表需要创建一个新的多边形图层,进行绘制。
关键代码:
//创建多边形图层
createPolygonLayer(coordinate) {
//存放当前点经纬度信息
this.currentCoordinates.push(coordinate);
//存放当前虚线经纬度信息
this.lineCoordinates.push(coordinate);
//创建多边形对象
const polygon = new Polygon([coordinate]);
//创建特征存放多边形对象
const polygonFeature = new Feature(polygon);
//创建数据源用于存放多个特征
const vectorSource = new VectorSource({
features: [polygonFeature],
});
//将数据源添加到图层上
const vectorLayer = new VectorLayer({
source: vectorSource,
style: new Style({
fill: new Fill({
color: 'rgba(255, 0, 0, 0.5)', // 填充颜色为红色
}),
stroke: new Stroke({
color: '#ffcc33',
width: 2,
}),
}),
});
this.map.addLayer(vectorLayer);
this.vectorLayers.push(vectorLayer);
},
3.4、创建点位
关键代码:
//添加点
addPoint(coordinate) {
//添加到当前经纬度集合
this.currentCoordinates.push(coordinate);
if (this.currentCoordinates.length > 2) {
this.updatePolygon();
}
},//添加点
addPoint(coordinate) {
//添加到当前线经纬度集合
this.lineCoordinates.push(coordinate);
//添加到当前点经纬度集合
this.currentCoordinates.push(coordinate);
if (this.currentCoordinates.length > 2) {
//更新多边形显示
this.updatePolygon();
}
},
3.5、更新多边形显示
关键代码:
//更新多边形显示
updatePolygon() {
// 更新正在绘制的多边形
const polygon = new Polygon([this.currentCoordinates]);
if (this.vectorLayers.length > 0) {
//因为一个图层只存放一个多边形特征,直接刷新它的经纬度信息
this.vectorLayers[this.vectorLayers.length - 1].getSource().getFeatures()[0].setGeometry(polygon);
}
},
3.6、开始绘制/结束绘制
关键代码:
//开始绘制
startDrawing(){
this.drawing = true;
//禁用开始绘制按钮
this.startButton = true;
//释放结束绘制按钮
this.endButton = false;
},
//结束绘制
endDrawing(){
this.drawing = false;
//直接和第一个点进行闭合
this.currentCoordinates.push(this.currentCoordinates[0]);
//更新多边形绘制
this.updatePolygon();
//将当前点经纬度信息置空
this.currentCoordinates = [];
//将当前线经纬度信息置空
this.lineCoordinates = [];
// 清除虚线
this.map.removeLayer(this.lineLayer);
this.lineLayer = null;
//释放开始绘制按钮
this.startButton = false;
//禁用结束绘制按钮
this.endButton = true;
},
3.7、创建/更新虚线显示
关键代码
updateLine(coordinate) {
if (this.lineLayer) {
// 更新现有虚线的最后一个坐标
this.lineCoordinates[this.lineCoordinates.length - 1] = coordinate; // 修改最后一点
const lineString = new LineString(this.lineCoordinates);
this.lineLayer.getSource().getFeatures()[0].setGeometry(lineString);
} else {
// 创建虚线图层
this.lineLayer = new VectorLayer({
source: new VectorSource({
features: [new Feature(new LineString([coordinate]))],
}),
style: new Style({
stroke: new Stroke({
color: 'rgba(0, 0, 255, 1)', // 虚线颜色
width: 2,
lineDash: [10, 10] // 设置虚线样式
}),
}),
});
this.map.addLayer(this.lineLayer);
this.lineCoordinates.push(coordinate);
}
},
3.8、初始化地图事件
关键代码:
//初始化地图点击事件
initMapClickEvent() {
let _that = this;
// 添加点击事件监听
this.map.on('click', (event) => {
if (this.drawing) {
//如果第一次点击则新建一个图层
if(_that.currentCoordinates.length <=0){
_that.createPolygonLayer(event.coordinate)
}else{
//否则把点直接添加到当前图层上
_that.addPoint(event.coordinate);
}
}
});
// 添加鼠标移动事件
this.map.on('pointermove', (event) => {
if (this.drawing) {
//更新线的位置
this.updateLine(event.coordinate);
}
});
},
3.9、完整代码
<template>
<div>
<el-button @click="startDrawing" :disabled="startButton" type="primary">开始绘制</el-button>
<el-button @click="endDrawing" :disabled="endButton" type="success">完成绘制</el-button>
<div id="map-container"></div>
</div>
</template>
<script>
import { Map, View } from 'ol'
import { Tile as TileLayer } from 'ol/layer'
import { get } from 'ol/proj';
import { getWidth, getTopLeft } from 'ol/extent'
import { WMTS } from 'ol/source'
import WMTSTileGrid from 'ol/tilegrid/WMTS'
import { defaults as defaultControls} from 'ol/control';
import { GeoJSON } from 'ol/format';
import { Vector as VectorLayer } from 'ol/layer';
import { Vector as VectorSource } from 'ol/source';
import { Feature } from 'ol';
import Polygon from 'ol/geom/Polygon';
import {Fill, Stroke, Style} from "ol/style";
import {LineString} from "ol/geom";
export const projection = get("EPSG:4326");
const projectionExtent = projection.getExtent();
const size = getWidth(projectionExtent) / 256;
const resolutions = [];
for (let z = 0; z < 19; ++z) {
resolutions[z] = size / Math.pow(2, z);
}
export default {
data() {
return {
map:null,
drawing: false,
//是否禁用开始绘制按钮
startButton:false,
//是否禁用结束绘制按钮
endButton:true,
//存放当前经纬度集合
currentCoordinates: [],
//图层多边形图层级
vectorLayers: [],
// 存储虚线图层
lineLayer: null,
// 存储虚线经纬度
lineCoordinates:[],
}
},
mounted(){
this.initMap() // 加载矢量底图
},
methods:{
initMap() {
const KEY = '你申请的KEY'
this.map = new Map({
target: 'map-container',
layers: [
// 底图
new TileLayer({
source: new WMTS({
url: `http://t{0-6}.tianditu.com/vec_c/wmts?tk=${KEY}`,
layer: 'vec', // 矢量底图
matrixSet: 'c', // c: 经纬度投影 w: 球面墨卡托投影
style: "default",
crossOrigin: 'anonymous', // 解决跨域问题 如无该需求可不添加
format: "tiles", //请求的图层格式,这里指定为瓦片格式
wrapX: true, // 允许地图在 X 方向重复(环绕)
tileGrid: new WMTSTileGrid({
origin: getTopLeft(projectionExtent),
resolutions: resolutions,
matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15','16','17','18']
})
})
}),
// 标注
new TileLayer({
source: new WMTS({
url: `http://t{0-6}.tianditu.com/cva_c/wmts?tk=${KEY}`,
layer: 'cva', //矢量注记
matrixSet: 'c',
style: "default",
crossOrigin: 'anonymous',
format: "tiles",
wrapX: true,
tileGrid: new WMTSTileGrid({
origin: getTopLeft(projectionExtent),
resolutions: resolutions,
matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15','16','17','18','19']
})
})
})
],
view: new View({
center: [120.430070,31.938140],
projection: projection,
zoom: 17,
maxZoom: 19,
minZoom: 1
}),
//加载控件到地图容器中
controls: defaultControls({
zoom: false,
rotate: false,
attribution: false
})
});
//初始化地图点击事件
this.initMapClickEvent();
//初始化一个基本的面
this.initBasePolygon();
},
//初始化一个基本的面
initBasePolygon() {
// 定义多边形的坐标
const coordinates = [
[
[120.430070,31.938140],
[120.428570,31.939100],
[120.429530,31.941680],
[120.431240,31.943580],
[120.432410,31.944820],
[120.433600,31.943970],
]
];
// 创建多边形对象
const polygon = new Polygon(coordinates);
// 创建特征
const polygonFeature = new Feature(polygon);
// 创建矢量图层并添加特征
const vectorSource = new VectorSource({
features: [polygonFeature]
});
const vectorLayer = new VectorLayer({
source: vectorSource,
style: new Style({
fill: new Fill({
color: 'rgba(255, 0, 0, 0.5)' // 填充颜色为红色
}),
stroke: new Stroke({
color: '#ffcc33',
width: 2
})
})
});
// 将矢量图层添加到地图中
this.map.addLayer(vectorLayer);
},
//初始化地图点击事件
initMapClickEvent() {
let _that = this;
// 添加点击事件监听
this.map.on('click', (event) => {
if (this.drawing) {
//如果第一次点击则新建一个图层
if(_that.currentCoordinates.length <=0){
_that.createPolygonLayer(event.coordinate)
}else{
//否则把点直接添加到当前图层上
_that.addPoint(event.coordinate);
}
}
});
// 添加鼠标移动事件
this.map.on('pointermove', (event) => {
if (this.drawing) {
//更新线的位置
this.updateLine(event.coordinate);
}
});
},
//添加点
addPoint(coordinate) {
//添加到当前线经纬度集合
this.lineCoordinates.push(coordinate);
//添加到当前点经纬度集合
this.currentCoordinates.push(coordinate);
if (this.currentCoordinates.length > 2) {
//更新多边形显示
this.updatePolygon();
}
},
//更新多边形显示
updatePolygon() {
// 更新正在绘制的多边形
const polygon = new Polygon([this.currentCoordinates]);
if (this.vectorLayers.length > 0) {
//因为一个图层只存放一个多边形特征,直接刷新它的经纬度信息
this.vectorLayers[this.vectorLayers.length - 1].getSource().getFeatures()[0].setGeometry(polygon);
}
},
//开始绘制
startDrawing(){
this.drawing = true;
//禁用开始绘制按钮
this.startButton = true;
//释放结束绘制按钮
this.endButton = false;
},
//结束绘制
endDrawing(){
this.drawing = false;
//直接和第一个点进行闭合
this.currentCoordinates.push(this.currentCoordinates[0]);
//更新多边形绘制
this.updatePolygon();
//将当前点经纬度信息置空
this.currentCoordinates = [];
//将当前线经纬度信息置空
this.lineCoordinates = [];
// 清除虚线
this.map.removeLayer(this.lineLayer);
this.lineLayer = null;
//释放开始绘制按钮
this.startButton = false;
//禁用结束绘制按钮
this.endButton = true;
},
//创建多边形图层
createPolygonLayer(coordinate) {
//存放当前点经纬度信息
this.currentCoordinates.push(coordinate);
//存放当前虚线经纬度信息
this.lineCoordinates.push(coordinate);
//创建多边形对象
const polygon = new Polygon([coordinate]);
//创建特征存放多边形对象
const polygonFeature = new Feature(polygon);
//创建数据源用于存放多个特征
const vectorSource = new VectorSource({
features: [polygonFeature],
});
//将数据源添加到图层上
const vectorLayer = new VectorLayer({
source: vectorSource,
style: new Style({
fill: new Fill({
color: 'rgba(255, 0, 0, 0.5)', // 填充颜色为红色
}),
stroke: new Stroke({
color: '#ffcc33',
width: 2,
}),
}),
});
this.map.addLayer(vectorLayer);
this.vectorLayers.push(vectorLayer);
},
updateLine(coordinate) {
if (this.lineLayer) {
// 更新现有虚线的最后一个坐标
this.lineCoordinates[this.lineCoordinates.length - 1] = coordinate; // 修改最后一点
const lineString = new LineString(this.lineCoordinates);
this.lineLayer.getSource().getFeatures()[0].setGeometry(lineString);
} else {
// 创建虚线图层
this.lineLayer = new VectorLayer({
source: new VectorSource({
features: [new Feature(new LineString([coordinate]))],
}),
style: new Style({
stroke: new Stroke({
color: 'rgba(0, 0, 255, 1)', // 虚线颜色
width: 2,
lineDash: [10, 10] // 设置虚线样式
}),
}),
});
this.map.addLayer(this.lineLayer);
this.lineCoordinates.push(coordinate);
}
},
},
}
</script>
<style scoped>
#map-container {
width: 100%;
height: 100vh;
}
</style>