Files
openlayers/examples/box-selection.js
mike-000 654f78388b Handle rotation in the Box Selection example
oblique rotations (i.e. not 0, 90, 180 or 270 degrees) require additional filtering of features intersecting the extent of the rotated box
2019-08-26 22:11:41 +01:00

99 lines
2.8 KiB
JavaScript

import Map from '../src/ol/Map.js';
import View from '../src/ol/View.js';
import {platformModifierKeyOnly} from '../src/ol/events/condition.js';
import GeoJSON from '../src/ol/format/GeoJSON.js';
import {DragBox, Select} from '../src/ol/interaction.js';
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
const vectorSource = new VectorSource({
url: 'data/geojson/countries.geojson',
format: new GeoJSON()
});
const map = new Map({
layers: [
new TileLayer({
source: new OSM()
}),
new VectorLayer({
source: vectorSource
})
],
target: 'map',
view: new View({
center: [0, 0],
zoom: 2,
constrainRotation: 16
})
});
// a normal select interaction to handle click
const select = new Select();
map.addInteraction(select);
const selectedFeatures = select.getFeatures();
// a DragBox interaction used to select features by drawing boxes
const dragBox = new DragBox({
condition: platformModifierKeyOnly
});
map.addInteraction(dragBox);
dragBox.on('boxend', function() {
// features that intersect the box geometry are added to the
// collection of selected features
// if the view is not obliquely rotated the box geometry and
// its extent are equalivalent so intersecting features can
// be added directly to the collection
const rotation = map.getView().getRotation();
const oblique = rotation % (Math.PI / 2) !== 0;
const candidateFeatures = oblique ? [] : selectedFeatures;
const extent = dragBox.getGeometry().getExtent();
vectorSource.forEachFeatureIntersectingExtent(extent, function(feature) {
candidateFeatures.push(feature);
});
// when the view is obliquely rotated the box extent will
// exceed its geometry so both the box and the candidate
// feature geometries are rotated around a common anchor
// to confirm that, with the box geometry aligned with its
// extent, the geometries intersect
if (oblique) {
const anchor = [0, 0];
const geometry = dragBox.getGeometry().clone();
geometry.rotate(-rotation, anchor);
const extent = geometry.getExtent();
candidateFeatures.forEach(function(feature) {
const geometry = feature.getGeometry().clone();
geometry.rotate(-rotation, anchor);
if (geometry.intersectsExtent(extent)) {
selectedFeatures.push(feature);
}
});
}
});
// clear selection when drawing a new box and when clicking on the map
dragBox.on('boxstart', function() {
selectedFeatures.clear();
});
const infoBox = document.getElementById('info');
selectedFeatures.on(['add', 'remove'], function() {
const names = selectedFeatures.getArray().map(function(feature) {
return feature.get('name');
});
if (names.length > 0) {
infoBox.innerHTML = names.join(', ');
} else {
infoBox.innerHTML = 'No countries selected';
}
});