UNPKG

hslayers-ng

Version:
191 lines (187 loc) 8.22 kB
import * as i0 from '@angular/core'; import { inject, Injectable } from '@angular/core'; import { Feature } from 'ol'; import { buffer, getCenter } from 'ol/extent'; import { getDomFeatureLinks, DOM_FEATURE_LINKS } from 'hslayers-ng/common/extensions'; import { isLayerVectorLayer, debounce, isLayerClustered, instOf } from 'hslayers-ng/services/utils'; import { HsLayoutService } from 'hslayers-ng/services/layout'; import { HsLogService } from 'hslayers-ng/services/log'; import { HsMapService } from 'hslayers-ng/services/map'; import { HsQueryBaseService, HsQueryVectorService } from 'hslayers-ng/services/query'; import { HsQueryPopupService } from 'hslayers-ng/common/query-popup'; class HsExternalService { constructor() { this.hsMapService = inject(HsMapService); this.hsLog = inject(HsLogService); this.hsQueryPopupService = inject(HsQueryPopupService); this.hsQueryBaseService = inject(HsQueryBaseService); this.hsQueryVectorService = inject(HsQueryVectorService); this.hsLayoutService = inject(HsLayoutService); this.featureLinks = {}; this.hsMapService.loaded().then((map) => { for (const layer of map.getLayers().getArray()) { this.layerAdded(layer); } map.getLayers().on('add', (e) => this.layerAdded(e.element)); map.getLayers().on('remove', (e) => this.layerRemoved(e.element)); }); } layerRemoved(layer) { if (isLayerVectorLayer(layer)) { for (const key of Object.keys(this.featureLinks)) { const link = this.featureLinks[key]; if (link.layer == layer) { this.removeFeatureLink(link); delete this.featureLinks[key]; } } } } /** * Registers DOM--feature links for newly added layer and * also sets listener for 'propertychange' in case the domFeatureLinks are changed later on. * The linked feature cannot be a RenderFeature. * @param layer - OL BaseLayer (superclass of Layer) */ layerAdded(layer) { if (!isLayerVectorLayer(layer)) { return; } if (getDomFeatureLinks(layer)) { this.processLinks(layer); } layer.on('propertychange', (e) => { debounce(this.layerPropChanged(e), 100, false, this); }); } layerPropChanged(e) { if (e.key == DOM_FEATURE_LINKS) { this.processLinks(e.target); } } processLinks(layer) { const source = isLayerClustered(layer) ? layer.getSource().getSource() : layer.getSource(); for (const link of getDomFeatureLinks(layer)) { const domElements = document.querySelectorAll(link.domSelector); domElements.forEach((domElement) => { const feature = this.getFeature(layer, source, link, domElement); if (!feature) { this.hsLog.error(`Cannot bind event ${link.event} from ${domElement} to feature ${link.feature}. Feature not found!`); return; } if (feature.getId() === undefined) { feature.setId(crypto.randomUUID()); } //We don't want to add handlers with the same feature and domElement twice if (feature && (!this.featureLinks[feature.getId()] || !this.featureLinks[feature.getId()].domElements.includes(domElement))) { const featureId = feature.getId(); //This was the only way how to unregister handlers afterwards const handler = (e) => { for (const action of link.actions) { this.actOnFeature(action, feature, domElement, e); } }; if (!this.featureLinks[featureId]) { this.featureLinks[featureId] = { handles: [], layer, domElements: [], event: link.event, }; } this.featureLinks[featureId].handles.push(handler); this.featureLinks[featureId].domElements.push(domElement); domElement.addEventListener(link.event, handler); } }); } source.on('removefeature', (event) => { if (!event.features) { return; } for (const removedFeature of event.features) { const linkage = this.featureLinks[removedFeature.getId()]; if (linkage) { this.removeFeatureLink(linkage); delete this.featureLinks[removedFeature.getId()]; } } }); } removeFeatureLink(linkage) { for (const handle of linkage.handles) { for (const domEl of linkage.domElements) { domEl.removeEventListener(linkage.event, handle); } } } actOnFeature(action, feature, domElement, e) { if (!this.hsMapService.getLayerForFeature(feature)?.getVisible()) { return; } const geom = feature.getGeometry(); // do not zoom strictly to the extent, but a bit bigger area - needed especially for points const extent = buffer(geom.getExtent(), 100); const center = getCenter(extent); const map = this.hsMapService.getMap(); switch (action) { case 'zoomToExtent': this.hsMapService.fitExtent(extent); break; case 'panToCenter': map.getView().setCenter(center); break; case 'showPopup': this.hsQueryPopupService.fillFeatures([feature]); const pixel = map.getPixelFromCoordinate(center); this.hsQueryPopupService.showPopup({ pixel, map }); break; case 'hidePopup': this.hsQueryPopupService.closePopup(); break; case 'select': const select = this.hsQueryBaseService.selector; select.getFeatures().clear(); this.hsQueryBaseService.clear('features'); select.getFeatures().push(feature); this.hsQueryVectorService.createFeatureAttributeList(); this.hsLayoutService.setMainPanel('query'); this.hsLayoutService.sidebarExpanded = true; break; default: if (typeof action == 'function') { action(feature, domElement, e); } } } getFeature(layer, source, link, domElement) { if (typeof link.feature == 'string' || typeof link.feature == 'number') { const featureLike = source.getFeatureById(link.feature); //Filter out possible RenderFeatures return featureLike instanceof Feature ? featureLike : undefined; } if (instOf(link.feature, Feature)) { return link.feature; } if (typeof link.feature == 'function') { return link.feature(layer, domElement); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: HsExternalService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: HsExternalService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.3", ngImport: i0, type: HsExternalService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: () => [] }); /** * Generated bundle index. Do not edit. */ export { HsExternalService }; //# sourceMappingURL=hslayers-ng-services-external.mjs.map