New example

New example

New example

lints

New example

New example

New example
This commit is contained in:
mike-000
2021-06-26 11:48:04 +01:00
parent 443b629f7e
commit aac9d6dd95
2 changed files with 299 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
---
layout: example.html
title: Measure using vector styles
shortdesc: Example of measuring lengths and areas using vector styles.
docs: >
<p>Using vector styles instead of overlays makes it easy to set up, then modify and
clear a measure. Additional information such as the lengths of individual segments
or sides can be included as required.</p>
<p>The <code>getLength()</code> and <code>getArea()</code>
functions calculate spherical lengths and areas for geometries. Lengths are
calculated by assuming great circle segments between geometry coordinates.
Areas are calculated as if edges of polygons were great circle segments.</p>
<p>Note that the <code>geometry.getLength()</code> and <code>geometry.getArea()</code>
methods return measures of projected (planar) geometries. These can be very
different than on-the-ground measures in certain situations — in northern
and southern latitudes using Web Mercator for example. For better results,
use the functions in the <code>ol/sphere</code> module.</p>
tags: "draw, edit, measure, modify, style, vector"
---
<div id="map" class="map"></div>
<form class="form-inline">
<label for="type">Measurement type &nbsp;</label>
<select id="type">
<option value="LineString">Length (LineString)</option>
<option value="Polygon">Area (Polygon)</option>
</select>
&nbsp;&nbsp;&nbsp;&nbsp;
<label for="segments">Show segment lengths:&nbsp;</label>
<input type="checkbox" id="segments" checked />
&nbsp;&nbsp;&nbsp;&nbsp;
<label for="clear">Clear previous measure:&nbsp;</label>
<input type="checkbox" id="clear" checked />
</form>

266
examples/measure-style.js Normal file
View File

@@ -0,0 +1,266 @@
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});
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
) {
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 () {
modify.setActive(true);
tip = idleTip;
});
modify.setActive(true);
map.addInteraction(draw);
}
typeSelect.onchange = function () {
map.removeInteraction(draw);
addInteraction();
};
addInteraction();
showSegments.onchange = function () {
vector.changed();
};