import Draw from 'ol/interaction/Draw'; import Overlay from 'ol/Overlay'; import { Circle as CircleStyle, Fill, Stroke, Style } from 'ol/style'; import { LineString, Polygon } from 'ol/geom'; import VectorSource from "ol/source/Vector"; import VectorLayer from "ol/layer/Vector"; import { getArea, getLength } from 'ol/sphere'; import { unByKey } from 'ol/Observable'; class measureTool { constructor(map) { this.map = map; this.source = new VectorSource(); this.vector = new VectorLayer({ source: this.source, zIndex: 1000, style: new Style({ fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)', }), stroke: new Stroke({ color: '#ffcc33', width: 2, }), image: new CircleStyle({ radius: 7, fill: new Fill({ color: '#ffcc33', }), }), }), }); this.map.addLayer(this.vector); /** * Currently drawn feature. * @type {import("../src/ol/Feature.js").default} */ this.sketch; /** * The help tooltip element. * @type {HTMLElement} */ this.helpTooltipElement; /** * Overlay to show the help messages. * @type {Overlay} */ this.helpTooltip; /** * The measure tooltip element. * @type {HTMLElement} */ this.measureTooltipElement; /** * Overlay to show the measurement. * @type {Overlay} */ this.measureTooltip; this.overlayArr = []; /** * Message to show when the user is drawing a polygon. * @type {string} */ this.continuePolygonMsg = '继续点击地图绘制测量区域'; /** * Message to show when the user is drawing a line. * @type {string} */ this.continueLineMsg = '继续点击地图绘制测量路线'; this.draw; // global so we can remove it later this.createHelpTooltip(); } start(measureType) { let that = this; const type = measureType == 'area' ? 'Polygon' : 'LineString'; this.draw = new Draw({ source: this.source, type: type, style: new Style({ fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)', }), stroke: new Stroke({ color: 'rgba(0, 0, 0, 0.5)', lineDash: [10, 10], width: 2, }), image: new CircleStyle({ radius: 5, stroke: new Stroke({ color: 'rgba(0, 0, 0, 0.7)', }), fill: new Fill({ color: 'rgba(255, 255, 255, 0.2)', }), }), }), }); this.map.addInteraction(this.draw); this.pointermove_event = this.map.on('pointermove', function (evt) { if (evt.dragging) { return; } /** @type {string} */ let helpMsg = '点击地图进行测量'; if (that.sketch) { const geom = that.sketch.getGeometry(); if (geom instanceof Polygon) { helpMsg = that.continuePolygonMsg; } else if (geom instanceof LineString) { helpMsg = that.continueLineMsg; } } that.helpTooltipElement.innerHTML = helpMsg; that.helpTooltip.setPosition(evt.coordinate); that.helpTooltipElement.classList.remove('hidden'); }); this.map.getViewport().addEventListener('mouseout', d); function d(params) { if (that.helpTooltipElement == null || that.helpTooltipElement == undefined) { that.map.getViewport().removeEventListener('mouseout', d); return; } that.helpTooltipElement.classList.add('hidden'); } let listener; this.draw.on('drawstart', function (evt) { that.createMeasureTooltip() // set sketch that.sketch = evt.feature; /** @type {import("../src/ol/coordinate.js").Coordinate|undefined} */ let tooltipCoord = evt.coordinate; listener = that.sketch.getGeometry().on('change', function (evt) { const geom = evt.target; let output; if (geom instanceof Polygon) { output = that.formatArea(geom); tooltipCoord = geom.getInteriorPoint().getCoordinates(); } else if (geom instanceof LineString) { output = that.formatLength(geom); tooltipCoord = geom.getLastCoordinate(); } that.measureTooltipElement.innerHTML = output; that.measureTooltip.setPosition(tooltipCoord); }); }); this.draw.on('drawend', function () { that.measureTooltipElement.className = 'ol-tooltip ol-tooltip-static'; that.measureTooltip.setOffset([0, -7]); that.overlayArr.push(that.measureTooltip); // unset sketch that.sketch = null; // unset tooltip so that a new one can be created // that.measureTooltipElement.innerHTML = ""; unByKey(listener); }); } /** * Creates a new help tooltip */ createHelpTooltip() { this.helpTooltipElement = document.createElement('div'); this.helpTooltipElement.className = 'ol-tooltip hidden'; this.helpTooltip = new Overlay({ element: this.helpTooltipElement, offset: [15, 0], positioning: 'center-left', }); this.map.addOverlay(this.helpTooltip); } /** * Creates a new measure tooltip */ createMeasureTooltip() { this.measureTooltipElement = document.createElement('div'); this.measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure'; this.measureTooltip = new Overlay({ element: this.measureTooltipElement, offset: [0, -15], positioning: 'bottom-center', stopEvent: false, insertFirst: false, }); this.map.addOverlay(this.measureTooltip); } /** * Format length output. * @param {LineString} line The line. * @return {string} The formatted length. */ formatLength(line) { const length = getLength(line); let output; if (length > 100) { output = Math.round((length / 1000) * 100) / 100 + ' ' + 'km'; } else { output = Math.round(length * 100) / 100 + ' ' + 'm'; } return output; }; /** * Format area output. * @param {Polygon} polygon The polygon. * @return {string} Formatted area. */ formatArea(polygon) { const area = getArea(polygon); let output; if (area > 10000) { output = Math.round((area / 1000000) * 100) / 100 + ' ' + 'km2'; } else { output = Math.round(area * 100) / 100 + ' ' + 'm2'; } return output; }; stop() { let that = this; if (this.draw) { this.map.removeInteraction(this.draw); this.draw = null; unByKey(this.pointermove_event); if (this.helpTooltip) { this.helpTooltip.setPosition(undefined) } if (this.measureTooltip) { this.measureTooltip.setPosition(undefined) } if (this.overlayArr.length > 0) { this.overlayArr.map(function (item) { that.map.removeOverlay(item); }) this.overlayArr = []; } if (this.source.getFeatures().length != 0) { this.source.getFeatures().forEach(function (feature) { that.source.removeFeature(feature) }) } } } } export default measureTool