UNPKG

@geogirafe/lib-geoportal

Version:

GeoGirafe is a flexible application to build online geoportals.

136 lines (135 loc) 5.5 kB
// SPDX-License-Identifier: Apache-2.0 import View from 'ol/View.js'; import { get as getProjection, transform } from 'ol/proj.js'; import GeoConsts from '../../../tools/geoconsts.js'; class ViewManager { map; get state() { return this.stateManager.state; } get projection() { return getProjection(this.state.projection); } configManager; stateManager; scales; allowedResolutions; constrainScales; constrainRotation; view; constructor(map, configManager, stateManager) { this.map = map; this.configManager = configManager; this.stateManager = stateManager; this.constrainScales = this.configManager.Config.map.constrainScales; this.constrainRotation = this.configManager.Config.map.constrainRotation; this.scales = this.configManager.Config.map.scales; this.allowedResolutions = this.scalesToResolutions(this.scales); this.view = new View({ center: this.configManager.Config.map.startPosition.split(',').map(Number), zoom: Number(this.configManager.Config.map.startZoom), projection: this.configManager.getDefaultConfigValue('map.srid'), extent: this.configManager.Config.map.maxExtent?.split(',').map(Number), resolutions: this.allowedResolutions, constrainResolution: this.constrainScales, constrainRotation: this.constrainRotation }); this.updateStatePosition(); this.stateManager.subscribe(/position(\..*)?/, (_, _newValue) => this.onPositionChanged()); } scalesToResolutions(scales) { const resolutions = new Array(); scales.forEach((scale) => { const resolution = this.scaleToResolution(scale); resolutions.push(resolution); }); return resolutions; } scaleToResolution(scale) { const unit = this.projection.getUnits(); const resolution = scale / GeoConsts.METERS_PER_UNIT[unit] / GeoConsts.INCHES_PER_METER / GeoConsts.SCREEN_DOTS_PER_INCH; return resolution; } getScale() { const unit = this.projection.getUnits(); const resolution = this.view.getResolution(); const scale = resolution * GeoConsts.METERS_PER_UNIT[unit] * GeoConsts.INCHES_PER_METER * GeoConsts.SCREEN_DOTS_PER_INCH; return scale; } updateStatePosition() { const mapPosition = this.state.position.clone(); mapPosition.center = this.view.getCenter(); const currentResolution = this.view.getResolution(); if (currentResolution && currentResolution > 0) { mapPosition.resolution = currentResolution; } mapPosition.zoom = this.view.getZoom() ?? mapPosition.zoom; mapPosition.scale = this.getScale(); this.state.position = mapPosition; } getDefaultView() { return this.view; } getViewConvertedToSrid(newSrid) { const currentView = this.view; const currentProjection = currentView.getProjection(); if (currentProjection.getCode() === newSrid) { // Nothing to do return currentView; } // Convert old values... const currentCenter = currentView.getCenter(); const currentRotation = currentView.getRotation(); // ... to new ones const newCenter = transform(currentCenter, currentProjection, this.projection); this.allowedResolutions = this.scalesToResolutions(this.scales); // If there is a configured max extent, convert it. const currentExtent = currentView.get('extent'); let newExtent; if (currentExtent) { const newExtentPoint1 = transform([currentExtent[0], currentExtent[1]], currentProjection, this.projection); const newExtentPoint2 = transform([currentExtent[2], currentExtent[3]], currentProjection, this.projection); newExtent = [newExtentPoint1[0], newExtentPoint1[1], newExtentPoint2[0], newExtentPoint2[1]]; } const newView = new View({ center: newCenter, zoom: currentView.getZoom(), rotation: currentRotation, projection: this.projection, resolutions: this.allowedResolutions, constrainResolution: this.constrainScales, constrainRotation: this.constrainRotation, extent: newExtent }); this.view = newView; this.updateStatePosition(); return this.view; } onPositionChanged() { const position = this.state.position; if (position.zoom && position.zoom !== this.view.getZoom()) { this.view.setZoom(position.zoom); } else if (position.resolution && position.resolution !== this.view.getResolution() && position.resolution >= 0) { this.view.setResolution(position.resolution); } else if (position.scale && position.scale !== this.getScale()) { this.setScale(position.scale); } if (position.center && position.center.length === 2 && position.center !== this.view.getCenter()) { this.view.setCenter(position.center); } this.updateStatePosition(); } setScale(scale) { const resolution = this.scaleToResolution(scale); this.view.setResolution(resolution); } } export default ViewManager;