New example
New example New example lints New example New example New example
This commit is contained in:
33
examples/measure-style.html
Normal file
33
examples/measure-style.html
Normal 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 </label>
|
||||
<select id="type">
|
||||
<option value="LineString">Length (LineString)</option>
|
||||
<option value="Polygon">Area (Polygon)</option>
|
||||
</select>
|
||||
|
||||
<label for="segments">Show segment lengths: </label>
|
||||
<input type="checkbox" id="segments" checked />
|
||||
|
||||
<label for="clear">Clear previous measure: </label>
|
||||
<input type="checkbox" id="clear" checked />
|
||||
</form>
|
||||
266
examples/measure-style.js
Normal file
266
examples/measure-style.js
Normal 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();
|
||||
};
|
||||
Reference in New Issue
Block a user