UNPKG

@geogirafe/lib-geoportal

Version:

GeoGirafe is a flexible application to build online geoportals.

125 lines (124 loc) 5 kB
// SPDX-License-Identifier: Apache-2.0 import GirafeSingleton from '../../base/GirafeSingleton.js'; import { isSnappableLayer } from '../../models/layers/snappablelayer.js'; import SelectionParam from '../../models/selectionparam.js'; import Snap from 'ol/interaction/Snap.js'; import { Collection } from 'ol'; class SnapManager extends GirafeSingleton { activeSnapLayers = new Map(); inactiveSnapLayers = []; get olMap() { return this.context.mapManager.getMap(); } get state() { return this.context.stateManager.state; } initializeSingleton() { this.context.stateManager.subscribe(/layers\.layersList\..*\.activeState/, (_oldActive, _newActive, layer) => { this.layerUpdated(layer); }); this.context.stateManager.subscribe(/layers\.layersList\..*\.snapActive/, (_oldSnap, _newSnap, layer) => { this.layerUpdated(layer); }); this.context.stateManager.subscribe('layers.isSnappingActive', (_, isSnappingActive) => { if (isSnappingActive) { this.activateSnappingForAllLayers(); } else { this.deactivateSnappingForAllLayers(); } }); this.olMap .getInteractions() .on('add', (event) => this.mapInteractionsChanged(event.element)); } mapInteractionsChanged(interaction) { if (!(interaction instanceof Snap)) { for (const options of this.activeSnapLayers.values()) { // Snapping interactions have to be removed and readded, because they mut be the last ones in the list of interactions // This is a limitation of OpenLayers. Otherwise the drawing interaction will prevail to the snapping one // And snapping won't work when the drawing tool is changed. this.olMap.removeInteraction(options.snapInteraction); this.olMap.addInteraction(options.snapInteraction); } } } activateSnappingForAllLayers() { for (const layer of this.inactiveSnapLayers) { const snapOptions = this.createSnapOptions(layer); this.registerLayer(layer, snapOptions); } this.inactiveSnapLayers = []; } deactivateSnappingForAllLayers() { const layersToDeactivate = Array.from(this.activeSnapLayers.keys()); for (const layer of layersToDeactivate) { this.unregisterLayer(layer); this.inactiveSnapLayers.push(layer); } } layerUpdated(layer) { if (!isSnappableLayer(layer)) { // Nothing to do return; } if (layer.active && layer.snapActive) { if (this.state.layers.isSnappingActive) { const snapOptions = this.createSnapOptions(layer); this.registerLayer(layer, snapOptions); } else { this.inactiveSnapLayers.push(layer); } } else { this.unregisterLayer(layer); } } createSnapOptions(layer) { const snapFeatures = new Collection(); const options = layer.snapOptions || {}; const interaction = new Snap({ edge: options.edge, features: snapFeatures, pixelTolerance: options.tolerance, vertex: options.vertex }); const snapOptions = { active: layer.snapActive, snapInteraction: interaction, snapFeatures: snapFeatures }; return snapOptions; } registerLayer(layer, snapOptions) { this.activeSnapLayers.set(layer, snapOptions); this.loadFeaturesForLayer(layer, snapOptions); snapOptions.snapInteraction.setActive(true); this.olMap.addInteraction(snapOptions.snapInteraction); this.olMap.getView().un('change', this.reloadFeatures.bind(this)); this.olMap.getView().on('change', this.reloadFeatures.bind(this)); } unregisterLayer(layer) { const snapOptions = this.activeSnapLayers.get(layer); if (snapOptions) { snapOptions.snapInteraction.setActive(false); snapOptions.snapFeatures.clear(); this.olMap.removeInteraction(snapOptions.snapInteraction); this.activeSnapLayers.delete(layer); } } reloadFeatures() { for (const [layer, options] of this.activeSnapLayers) { this.loadFeaturesForLayer(layer, options); } } async loadFeaturesForLayer(layer, options) { const client = this.context.wfsManager.getClient(layer.ogcServer); const extent = this.olMap.getView().getViewStateAndExtent().extent; const selectionParam = new SelectionParam(layer.ogcServer, [layer], this.state.projection, extent); const features = await client.getFeature(selectionParam); options.snapFeatures.extend(features); } } export default SnapManager;