UNPKG

gmap-ol

Version:

A set of helper classes for working with openLayers.

269 lines (254 loc) 7.78 kB
import Feature from 'ol/Feature'; import { Draw, Modify } from 'ol/interaction'; import { LineString, Point } from 'ol/geom'; import { Vector as VectorSource } from 'ol/source'; import { Vector as VectorLayer } from 'ol/layer'; import { getArea, getLength } from 'ol/sphere'; import { style, labelStyle, tipStyle, modifyStyle, segmentStyle, clearStyle } from './StyleConfig.js'; let globalMap = null; let draw; // global so we can remove it later let drawType = 'LineString'; // 测量类型: LineString, Polygon let showSegments = true; // 显示段长度 let clearPrevious = true; // 清除先前的测量数据 const segmentStyles = [segmentStyle]; const source = new VectorSource(); let modify = new Modify({ source: source, style: modifyStyle }); let tipPoint; // 初始调用一次,加载绘制图层。 let isFirst = true; function onceFunction() { if (isFirst) { globalMap.addLayer(drawLayer); globalMap.addLayer(clearLayer); globalMap.addInteraction(modify); isFirst = false; } } /** * 测量距离 * * @param {import("ol/Map").default} map An OlMap. * * @return {number} The length of line in meters. */ export function measureLength(olmap, measureOption, measureCallbackFn) { if (olmap === null || olmap === undefined) { return; // 终止函数执行 } globalMap = olmap; drawType = 'LineString'; onceFunction(); if (draw) { let drawInteraction; olmap.getInteractions().forEach((interaction) => { if (interaction instanceof Draw) { drawInteraction = interaction; } }); // 从地图上移除该交互。 if (drawInteraction) { olmap.removeInteraction(drawInteraction); } } addInteractionFn(measureCallbackFn); if (measureOption) { showSegments = measureOption?.showSegments; clearPrevious = measureOption?.clearPrevious; } } /** * 测量面积 * * @param {import("ol/Map").default} map An OlMap. * * @return {number} The area of the polygon in square meter. */ export function measureArea(olmap, measureOption, measureCallbackFn) { globalMap = olmap; drawType = 'Polygon'; onceFunction(); if (draw) { let drawInteraction; olmap.getInteractions().forEach((interaction) => { if (interaction instanceof Draw) { drawInteraction = interaction; } }); // 从地图上移除该交互。 if (drawInteraction) { olmap.removeInteraction(drawInteraction); } } addInteractionFn(measureCallbackFn); if (measureOption) { showSegments = measureOption?.showSegments; clearPrevious = measureOption?.clearPrevious; } } /** * 清除测量 * * @param {import("ol/Map").default} map An OlMap. * * @return {number} The area of the polygon in square meter. */ export function clearMeasure() { source.clear(); drawLayer.getSource().clear(); clearLayer.getSource().clear(); } // 清除按钮 const clearLayer = new VectorLayer({ source: new VectorSource(), zIndex: 1100, }); // 绘制图层 const drawLayer = new VectorLayer({ source: new VectorSource(), style: function (feature) { return styleFunction(feature, showSegments); }, zIndex: 1000, }); const addInteractionFn = (measureCallbackFn) => { const activeTip = '单击以继续绘制' + (drawType === 'Polygon' ? '多边形' : '线'); const idleTip = '点击开始测量'; let tip = idleTip; draw = new Draw({ source: source, type: drawType, style: (feature) => { return styleFunction(feature, showSegments, drawType, tip); }, }); draw.on('drawstart', () => { if (clearPrevious) { clearMeasure(); } modify.setActive(false); tip = activeTip; }); draw.on('drawend', (event) => { drawLayer.getSource().addFeature(event.feature); modifyStyle.setGeometry(tipPoint); modify.setActive(true); globalMap.once('pointermove', () => { modifyStyle.setGeometry(); }); tip = idleTip; // 结束绘制,清除draw globalMap.once('dblclick', (event) => { event.map.removeInteraction(draw); }); globalMap.on('singleclick', (event) => { const pixel = event.map.getEventPixel(event.originalEvent); const feature = event.map.forEachFeatureAtPixel(pixel, (feature) => { return feature.getProperties(); }); if (feature?.name === 'ClearPoint') { clearMeasure(); } }); globalMap.on('pointermove', (event) => { const pixel = event.map.getEventPixel(event.originalEvent); const feature = event.map.forEachFeatureAtPixel(pixel, (feature) => { return feature.getProperties(); }); event.map.getTargetElement().style.cursor = 'auto'; if (feature?.name === 'ClearPoint') { event.map.getTargetElement().style.cursor = 'pointer'; } }); // 回调函数,返回测量的数据 setTimeout(() => { const features = drawLayer.getSource().getFeatures(); const geometryData = features[features.length - 1].getGeometry(); let measure = ''; if (drawType === 'LineString') { measure = formatLength(geometryData); } else { measure = formatArea(geometryData); } return measureCallbackFn ? measureCallbackFn(measure) : null; }, 100); }); modify.setActive(true); globalMap.addInteraction(draw); }; // 计算距离 const formatLength = (line) => { let sourceProj = globalMap.getView().getProjection(); //获取投影坐标系 const length = getLength(line, { projection: sourceProj }); let output; if (length > 100) { output = Math.round((length / 1000) * 100) / 100 + ' km'; } else { output = Math.round(length * 100) / 100 + ' m'; } return output; }; // 计算面积 const formatArea = (polygon) => { let sourceProj = globalMap.getView().getProjection(); //获取投影坐标系 const area = getArea(polygon, { projection: sourceProj }); let output; if (area > 10000) { output = Math.round((area / 1000000) * 100) / 100 + ' km\xB2'; } else { output = Math.round(area * 100) / 100 + ' m\xB2'; } return output; }; const styleFunction = (feature, segments, drawType, tip) => { const styles = [style]; const geometry = feature.getGeometry(); const type = geometry.getType(); let point, label, line; if (!drawType || drawType === type) { if (type === 'Polygon') { point = geometry.getInteriorPoint(); label = formatArea(geometry); line = new LineString(geometry.getCoordinates()[0]); } else if (type === 'LineString') { point = new Point(geometry.getLastCoordinate()); label = formatLength(geometry); line = geometry; } } if (segments && line) { let count = 0; line.forEachSegment((a, b) => { const segment = new LineString([a, b]); const label = formatLength(segment); if (segmentStyles.length - 1 < count) { segmentStyles.push(segmentStyle.clone()); } const segmentPoint = new Point(segment.getCoordinateAt(0.5)); segmentStyles[count].setGeometry(segmentPoint); segmentStyles[count].getText().setText(label); styles.push(segmentStyles[count]); count++; }); } if (label) { labelStyle.setGeometry(point); labelStyle.getText().setText(label); styles.push(labelStyle); } if (tip && type === 'Point' && !modify.getOverlay().getSource().getFeatures().length) { tipPoint = geometry; tipStyle.getText().setText(tip); styles.push(tipStyle); } // 添加删除按钮 if (!drawType) { clearLayer.getSource().clear(); const iconFeature = new Feature({ geometry: new Point(point.flatCoordinates), name: 'ClearPoint', }); iconFeature.setStyle(clearStyle); clearLayer.getSource().addFeature(iconFeature); } return styles; };