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