275 lines
6.3 KiB
JavaScript
275 lines
6.3 KiB
JavaScript
import Map from '../src/ol/Map.js';
|
|
import View from '../src/ol/View.js';
|
|
import {
|
|
Circle as CircleStyle,
|
|
Fill,
|
|
RegularShape,
|
|
Stroke,
|
|
Style,
|
|
Text,
|
|
} from '../src/ol/style.js';
|
|
import {Draw, Modify} from '../src/ol/interaction.js';
|
|
import {LineString, Point} from '../src/ol/geom.js';
|
|
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
|
|
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
|
import {getArea, getLength} from '../src/ol/sphere.js';
|
|
|
|
const typeSelect = document.getElementById('type');
|
|
const showSegments = document.getElementById('segments');
|
|
const clearPrevious = document.getElementById('clear');
|
|
|
|
const 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)',
|
|
}),
|
|
}),
|
|
});
|
|
|
|
const labelStyle = new Style({
|
|
text: new Text({
|
|
font: '14px Calibri,sans-serif',
|
|
fill: new Fill({
|
|
color: 'rgba(255, 255, 255, 1)',
|
|
}),
|
|
backgroundFill: new Fill({
|
|
color: 'rgba(0, 0, 0, 0.7)',
|
|
}),
|
|
padding: [3, 3, 3, 3],
|
|
textBaseline: 'bottom',
|
|
offsetY: -15,
|
|
}),
|
|
image: new RegularShape({
|
|
radius: 8,
|
|
points: 3,
|
|
angle: Math.PI,
|
|
displacement: [0, 10],
|
|
fill: new Fill({
|
|
color: 'rgba(0, 0, 0, 0.7)',
|
|
}),
|
|
}),
|
|
});
|
|
|
|
const tipStyle = new Style({
|
|
text: new Text({
|
|
font: '12px Calibri,sans-serif',
|
|
fill: new Fill({
|
|
color: 'rgba(255, 255, 255, 1)',
|
|
}),
|
|
backgroundFill: new Fill({
|
|
color: 'rgba(0, 0, 0, 0.4)',
|
|
}),
|
|
padding: [2, 2, 2, 2],
|
|
textAlign: 'left',
|
|
offsetX: 15,
|
|
}),
|
|
});
|
|
|
|
const modifyStyle = new Style({
|
|
image: new CircleStyle({
|
|
radius: 5,
|
|
stroke: new Stroke({
|
|
color: 'rgba(0, 0, 0, 0.7)',
|
|
}),
|
|
fill: new Fill({
|
|
color: 'rgba(0, 0, 0, 0.4)',
|
|
}),
|
|
}),
|
|
text: new Text({
|
|
text: 'Drag to modify',
|
|
font: '12px Calibri,sans-serif',
|
|
fill: new Fill({
|
|
color: 'rgba(255, 255, 255, 1)',
|
|
}),
|
|
backgroundFill: new Fill({
|
|
color: 'rgba(0, 0, 0, 0.7)',
|
|
}),
|
|
padding: [2, 2, 2, 2],
|
|
textAlign: 'left',
|
|
offsetX: 15,
|
|
}),
|
|
});
|
|
|
|
const segmentStyle = new Style({
|
|
text: new Text({
|
|
font: '12px Calibri,sans-serif',
|
|
fill: new Fill({
|
|
color: 'rgba(255, 255, 255, 1)',
|
|
}),
|
|
backgroundFill: new Fill({
|
|
color: 'rgba(0, 0, 0, 0.4)',
|
|
}),
|
|
padding: [2, 2, 2, 2],
|
|
textBaseline: 'bottom',
|
|
offsetY: -12,
|
|
}),
|
|
image: new RegularShape({
|
|
radius: 6,
|
|
points: 3,
|
|
angle: Math.PI,
|
|
displacement: [0, 8],
|
|
fill: new Fill({
|
|
color: 'rgba(0, 0, 0, 0.4)',
|
|
}),
|
|
}),
|
|
});
|
|
|
|
const segmentStyles = [segmentStyle];
|
|
|
|
const formatLength = function (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;
|
|
};
|
|
|
|
const formatArea = function (polygon) {
|
|
const area = getArea(polygon);
|
|
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 raster = new TileLayer({
|
|
source: new OSM(),
|
|
});
|
|
|
|
const source = new VectorSource();
|
|
|
|
const modify = new Modify({source: source, style: modifyStyle});
|
|
|
|
let tipPoint;
|
|
|
|
function 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(function (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);
|
|
}
|
|
return styles;
|
|
}
|
|
|
|
const vector = new VectorLayer({
|
|
source: source,
|
|
style: function (feature) {
|
|
return styleFunction(feature, showSegments.checked);
|
|
},
|
|
});
|
|
|
|
const map = new Map({
|
|
layers: [raster, vector],
|
|
target: 'map',
|
|
view: new View({
|
|
center: [-11000000, 4600000],
|
|
zoom: 15,
|
|
}),
|
|
});
|
|
|
|
map.addInteraction(modify);
|
|
|
|
let draw; // global so we can remove it later
|
|
|
|
function addInteraction() {
|
|
const drawType = typeSelect.value;
|
|
const activeTip =
|
|
'Click to continue drawing the ' +
|
|
(drawType === 'Polygon' ? 'polygon' : 'line');
|
|
const idleTip = 'Click to start measuring';
|
|
let tip = idleTip;
|
|
draw = new Draw({
|
|
source: source,
|
|
type: drawType,
|
|
style: function (feature) {
|
|
return styleFunction(feature, showSegments.checked, drawType, tip);
|
|
},
|
|
});
|
|
draw.on('drawstart', function () {
|
|
if (clearPrevious.checked) {
|
|
source.clear();
|
|
}
|
|
modify.setActive(false);
|
|
tip = activeTip;
|
|
});
|
|
draw.on('drawend', function () {
|
|
modifyStyle.setGeometry(tipPoint);
|
|
modify.setActive(true);
|
|
map.once('pointermove', function () {
|
|
modifyStyle.setGeometry();
|
|
});
|
|
tip = idleTip;
|
|
});
|
|
modify.setActive(true);
|
|
map.addInteraction(draw);
|
|
}
|
|
|
|
typeSelect.onchange = function () {
|
|
map.removeInteraction(draw);
|
|
addInteraction();
|
|
};
|
|
|
|
addInteraction();
|
|
|
|
showSegments.onchange = function () {
|
|
vector.changed();
|
|
draw.getOverlay().changed();
|
|
};
|