距离测算,面积测算
最近超图项目要加一个测算功能,距离测算和面积测算,要求在用户鼠标落下之后给出提示,画完之后需要在区域内显示测算结果。最后决定使用overlay+动态添加dom的方式实现。
工具方法
utils.js
import Overlay from 'ol/Overlay'
// 这里是提示文字
export const helpTool = (map, sketch) => {
let helpTooltipElement;
// 清除历史提示图层
map.removeOverlay(map.getOverlayById('measurehelp'))
if (helpTooltipElement) {
helpTooltipElement.parentNode.removeChild(helpTooltipElement)
}
// 创建dom
helpTooltipElement = document.createElement('div')
helpTooltipElement.className = 'tooltip hidden'
helpTooltipElement.style.color = '#389bcb';
// 实例overlay
const helpTooltip = new Overlay({
id: 'measurehelp',
element: helpTooltipElement,
offset: [15, 0],
positioning: 'center-left',
})
map.addOverlay(helpTooltip)
// 笔触监听
let pointerMoveHandler = function (evt) {
if (evt.dragging) {
return
}
let helpMsg = '请点击开始绘制'
if (sketch) {
const geom = (sketch.getGeometry())
if (geom instanceof Polygon || geom instanceof LineString) {
helpMsg = ''
}
}
helpTooltipElement.innerHTML = helpMsg
helpTooltip.setPosition(evt.coordinate)
helpTooltipElement.classList.remove('hidden')
}
map.on('pointermove', pointerMoveHandler)
// 笔触移出地图后隐藏
map.getViewport().addEventListener('mouseout', () => {
helpTooltipElement.classList.add('hidden')
})
return { pointerMoveHandler, helpTooltipElement };
}
// 测量结果显示
export const measureTool = (map) => {
let measureTooltipElement;
// 清除历史渲染
map.removeOverlay(map.getOverlayById('measure'))
if (measureTooltipElement) {
measureTooltipElement.parentNode.removeChild(measureTooltipElement)
}
// 创建dom
measureTooltipElement = document.createElement('div')
measureTooltipElement.className = 'tooltip tooltip-measure'
// 实例overlay
let measureTooltip = new Overlay({
id: 'measure',
element: measureTooltipElement,
offset: [0, -15],
positioning: 'bottom-center',
})
map.addOverlay(measureTooltip);
return { measureTooltip, measureTooltipElement };
}
在页面中引入工具方法
import { getArea, getLength } from 'ol/sphere'
import { unByKey } from 'ol/Observable.js'
import { LineString, Polygon } from 'ol/geom.js'
import { helpTool, measureTool } from '../util.js'
export default {
data() {
return {
// 监听绘制元素变化
listener: null,
// 绘制元素
sketch: null,
// 笔触移动监听
pointerMoveHandler: null,
// 测绘结果提示
measureTooltip: null,
// 测绘结果提示的dom
measureTooltipElement: null,
// 提示dom
helpTooltipElement: null
}
},
methods: {
// 测量
measure(type) {
// 初始化画板
this.initDraw({
type,
});
// 测绘时的提示文字 和 测绘结果的提示文字
let help = helpTool(this.map),
measure = measureTool(this.map);
// 提示元素
this.helpTooltipElement = help.helpTooltipElement;
// 笔触移动监听
this.pointerMoveHandler = help.pointerMoveHandler;
// 测绘结果提示
this.measureTooltip = measure.measureTooltip;
// 测绘结果元素
this.measureTooltipElement = measure.measureTooltipElement;
// 测绘开始监听
this.draw.on('drawstart', (evt) => {
// 清除历史绘制
this.map.getLayers().getArray().forEach((layer) => {
if (layer.get('layerName') === 'drawLayer') {
layer.getSource().clear()
}
})
// 绘制元素
this.sketch = evt.feature
let tooltipCoord = evt.coordinate
// 监听绘制元素的变化
this.listener = this.sketch.getGeometry().on('change', (e) => {
const geom = e.target
let output
// 长度测量
if (geom instanceof LineString) {
const length = getLength(geom, {
projection: 'EPSG:' + this.EPSG
})
if (length > 100) {
output = `${(Math.round(length / 1000 * 100) / 100)} km`
} else {
output = `${(Math.round(length * 100) / 100)} m`
}
tooltipCoord = geom.getLastCoordinate()
} else if (geom instanceof Polygon) {
// 面积测量
const area = getArea(geom, {
projection: 'EPSG:' + this.EPSG
})
if (area > 10000) {
output = `${(Math.round(area / 1000000 * 100) / 100)} km<sup>2</sup>`
} else {
output = `${(Math.round(area * 100) / 100)} m<sup>2</sup>`
}
tooltipCoord = geom.getInteriorPoint().getCoordinates()
}
// 测绘结果显示
this.measureTooltipElement.innerHTML = output
this.measureTooltipElement.className = 'tooltip tooltip-static'
this.measureTooltip.setPosition(tooltipCoord)
})
})
// 绘制结束
this.draw.on('drawend', () => {
this.measureTooltipElement.className = 'tooltip tooltip-static'
this.measureTooltip.setOffset([0, -7])
this.sketch = null
this.helpTooltipElement.classList.add('hidden')
})
},
// 释放
unmeasure() {
// 清除绘制
this.map.getLayers().getArray().forEach((layer) => {
if (layer.get('layerName') === 'drawLayer') {
layer.getSource().clear()
}
})
// 清除提示
this.map.removeOverlay(this.map.getOverlayById('measure'))
// 清除监听
if (this.pointerMoveHandler) this.map.un('pointermove', this.pointerMoveHandler)
if (this.listener) unByKey(this.listener)
// 清除画板
this.removeDraw();
this.map.removeInteraction(this.draw);
}
}
};