前言
openlayers还提供了测量相关的api,可在地图上测量路线的长度,以及区域的面积。通过此api,可开发一个测量工具,进行长度和面积的测量
一、创建图层
import Draw, { createRegularPolygon } from 'ol/interaction/Draw.js';
import { getArea, getLength } from 'ol/sphere.js';
import Fill from 'ol/style/Fill.js';
import Stroke from 'ol/style/Stroke.js';
drawSource.value = new VectorSource({ wrapX: false });
const drawLayer = new VectorLayer({
source: drawSource.value,
style() {
return new Style({
fill: new Fill({
color: 'rgba(0, 176, 255, 0.4)', // 设置填充颜色和透明度
}),
stroke: new Stroke({
color: 'rgba(0, 176, 255, 1)',
width: 2,
}),
});
},
});
map.instance.addLayer(drawLayer)
二、绘制并测量
function handleSelectTool(key: any) {
if (draw.value) {
map.instance.removeInteraction(draw.value);
}
switch (key) {
case 'area': {
measure('Polygon'); // 测量区域大小
break;
}
case 'distance': {
measure('LineString'); // 测量路线长度
break;
}
// No default
}
}
const measureTooltipElement = ref(null);
const measureTooltip = ref(null);
const sketch = ref(null);
// 绘制方法
function measure(measureType: any) {
// 创建提示框(实时显示测量结果)
createMeasureTooltip();
draw.value = new Draw({
source: drawSource.value,
type: measureType,
style: {
'fill-color': 'rgba(0, 176, 255, 0.4)',
'stroke-color': 'rgba(0, 176, 255, 1)',
'stroke-width': 2,
'circle-radius': 6,
'circle-fill-color': 'rgba(0, 176, 255, 1)',
'circle-stroke-color': 'rgba(255, 255, 255, 1)',
'circle-stroke-width': 1,
},
});
map.instance?.addInteraction(draw.value);
let listener;
// 开始绘制的监听
draw.value.on('drawstart', (evt: any) => {
// set sketch
// 获取绘制的feature
sketch.value = evt.feature;
/** @type {module:ol/coordinate~Coordinate|undefined} */
let tooltipCoord = evt.coordinate;
// 监听绘制feature的大小的改变
listener = sketch.value.getGeometry().on('change', (evt: any) => {
const geom = evt.target;
let output;
if (geom instanceof Polygon) {
// 判断,绘制的是一个面积,计算面积的大小
output = formatArea(geom);
tooltipCoord = geom.getInteriorPoint().getCoordinates();
} else if (geom instanceof LineString) {
// 判断绘制的是路径,计算路径的长度
output = formatLength(geom);
tooltipCoord = geom.getLastCoordinate();
}
// 将计算结果,显示到弹出层中
measureTooltipElement.value.innerHTML = output;
measureTooltip.value.setPosition(tooltipCoord);
});
});
draw.value.on('drawend', () => {
measureTooltipElement.value.className = 'tooltip tooltip-static';
measureTooltip.value.setOffset([0, -7]);
// unset sketch
sketch.value = null;
// unset tooltip so that a new one can be created
measureTooltipElement.value = null;
unByKey(listener);
map.instance.removeInteraction(draw.value);
});
function createMeasureTooltip() {
if (measureTooltipElement.value) {
measureTooltipElement.value.remove();
}
measureTooltipElement.value = document.createElement('div');
measureTooltipElement.value.className = 'tooltip tooltip-measure';
measureTooltip.value = new Overlay({
element: measureTooltipElement.value,
offset: [0, -15],
positioning: 'bottom-center',
});
map.instance.addOverlay(measureTooltip.value);
measureTooltipArray.value.push(measureTooltip.value);
}
}
// 核心api,计算路径的长度
const formatLength = (line: any) => {
// getLength是openlayers提供的api
const length = getLength(line, { projection: 'EPSG:4326' });
const output =
length > 100
? `${Math.round((length / 1000) * 100) / 100} ` + `km`
: `${Math.round(length * 100) / 100} ` + `m`;
return output;
};
// 核心api,计算面积的大小
const formatArea = (polygon: any) => {
// getArea是openlayers提供的api
const area = getArea(polygon, { projection: 'EPSG:4326' });
const output =
area > 10_000
? `${Math.round((area / 1_000_000) * 100) / 100} ` + `km<sup>2</sup>`
: `${Math.round(area * 100) / 100} ` + `m<sup>2</sup>`;
return output;
};
测量长度或面积的时候,如果使用的不是
EPSG:3857(默认)坐标系,则需要设置成当前地图的坐标系,否则会导致计算不准确。