diff --git a/web/client/components/map/openlayers/Map.jsx b/web/client/components/map/openlayers/Map.jsx index 069c8f51b20..3e5550da1e9 100644 --- a/web/client/components/map/openlayers/Map.jsx +++ b/web/client/components/map/openlayers/Map.jsx @@ -353,34 +353,14 @@ class OpenlayersMap extends React.Component { * - custom grid set with custom extent. You need to customize the projection definition extent to make it work. * - custom grid set is partially supported by mapOptions.view.resolutions but this is not managed by projection change yet * - custom tile sizes - * ** NOTES**: If mapOptions.view.resolutions + mapOptions.view.projection are provided and match → will use them. - * - Else → will compute resolutions for provided/mapView projection. + * */ getResolutions = (srs) => { - // Resolve requested projection - const requestedProj = srs - ? getProjection(srs) - : (this.map?.getView()?.getProjection()); - const requestedSRS = normalizeSRS(srs || requestedProj.getCode()); - - // Check for explicitly configured resolutions + matching projection - const viewOptions = this.props?.mapOptions?.view || {}; - const configuredResolutions = viewOptions.resolutions; - const configuredResProjection = viewOptions.projection && normalizeSRS(viewOptions.projection); - - // If resolutions are explicitly configured *and* tied to a projection that matches our target, - // return them directly — avoids recomputation and ensures consistency with custom tile sources. - if ( - configuredResolutions && - Array.isArray(configuredResolutions) && - configuredResProjection && - requestedSRS === configuredResProjection - ) { - return configuredResolutions; + if (this.props.mapOptions && this.props.mapOptions.view && this.props.mapOptions.view.resolutions) { + return this.props.mapOptions.view.resolutions; } - - // Otherwise compute dynamically - const extent = requestedProj.getExtent(); + const projection = srs ? getProjection(srs) : this.map.getView().getProjection(); + const extent = projection.getExtent(); return getResolutionsForProjection( srs ?? this.map.getView().getProjection().getCode(), { @@ -533,34 +513,15 @@ class OpenlayersMap extends React.Component { }; createView = (center, zoom, projection, options, limits = {}) => { - const srs = normalizeSRS(projection); // limit has a crs defined const extent = limits.restrictedExtent && limits.crs && reprojectBbox(limits.restrictedExtent, limits.crs, normalizeSRS(projection)); - - // Determine whether to use configured resolutions - const configuredResolutions = options?.resolutions; - const configuredProj = normalizeSRS(options?.projection); - - let resolutionsToUse; - if (configuredResolutions && configuredProj === normalizeSRS(projection)) { - // use provided resolutions (keep backward compatibility) - resolutionsToUse = configuredResolutions; - } else { - // compute resolutions dynamically (e.g., EPSG:4326) - resolutionsToUse = this.getResolutions(normalizeSRS(projection)); - } - const newOptions = { - ...options, - projection: srs, - resolutions: resolutionsToUse, - extent: options?.extent !== undefined ? options.extent : extent - }; + const newOptions = !options || (options && !options.view) ? Object.assign({}, options, { extent }) : Object.assign({}, options); /* * setting the zoom level in the localConfig file is co-related to the projection extent(size) * it is recommended to use projections with the same coverage area (extent). If you want to have the same restricted zoom level (minZoom) */ const viewOptions = Object.assign({}, { - projection: srs, + projection: normalizeSRS(projection), center: [center.x, center.y], zoom: zoom, minZoom: limits.minZoom, @@ -569,10 +530,8 @@ class OpenlayersMap extends React.Component { // does not allow intermediary zoom levels // we need this at true to set correctly the scale box constrainResolution: true, - resolutions: this.getResolutions(srs) - }, - newOptions || {} - ); + resolutions: this.getResolutions(normalizeSRS(projection)) + }, newOptions || {}); return new View(viewOptions); }; diff --git a/web/client/components/map/openlayers/__tests__/Map-test.jsx b/web/client/components/map/openlayers/__tests__/Map-test.jsx index ec40f1c62b8..7af254ce988 100644 --- a/web/client/components/map/openlayers/__tests__/Map-test.jsx +++ b/web/client/components/map/openlayers/__tests__/Map-test.jsx @@ -1404,7 +1404,7 @@ describe('OpenlayersMap', () => { , document.getElementById("map") @@ -1460,7 +1460,7 @@ describe('OpenlayersMap', () => { , document.getElementById("map") @@ -1523,41 +1523,4 @@ describe('OpenlayersMap', () => { // center is modified expect(map.map.getView().getCenter()).toEqual([10.3346773790, 43.9323234388]); }); - it('should correctly apply view projection without propagating to zoom changes', () => { - const resolutions = [0.0005, 0.0004, 0.0003, 0.0002]; - const map = ReactDOM.render( - , - document.getElementById("map") - ); - - const view = map.map.getView(); - expect(view.getProjection().getCode()).toBe('EPSG:4326'); - expect(view.getResolutions()).toEqual(resolutions); // Custom resolutions applied - - // Simulate a zoom change - view.setZoom(3); - expect(view.getProjection().getCode()).toBe('EPSG:4326'); - - // Simulate receiving new props with a different projection - ReactDOM.render( - , - document.getElementById("map") - ); - - const updatedView = map.map.getView(); - updatedView.setZoom(5); - expect(updatedView.getProjection().getCode()).toBe('EPSG:3857'); - expect(updatedView.getResolutions()).toNotEqual(resolutions); - }); - }); diff --git a/web/client/components/print/MapPreview.jsx b/web/client/components/print/MapPreview.jsx index 0861f58de16..49a5d44b90a 100644 --- a/web/client/components/print/MapPreview.jsx +++ b/web/client/components/print/MapPreview.jsx @@ -149,8 +149,7 @@ class MapPreview extends React.Component { let mapOptions = !isEmpty(resolutions) || !isNil(this.props.rotation) ? { view: { ...(!isEmpty(resolutions) && {resolutions}), - rotation: !isNil(this.props.rotation) ? Number(this.props.rotation) : 0, - projection + rotation: !isNil(this.props.rotation) ? Number(this.props.rotation) : 0 } } : {};