diff --git a/src/ol/View.js b/src/ol/View.js index 561af1cb39..67c63fa475 100644 --- a/src/ol/View.js +++ b/src/ol/View.js @@ -653,7 +653,7 @@ class View extends BaseObject { /** * @private - * @param {number|undefined} opt_rotation + * @param {number=} opt_rotation Take into account the rotation of the viewport when giving the size * @return {import("./size.js").Size} Viewport size or `[100, 100]` when no viewport is found. */ getSizeFromViewport_(opt_rotation) { @@ -666,8 +666,10 @@ class View extends BaseObject { size[1] = parseInt(metrics.height, 10); } if (opt_rotation) { - size[0] = Math.abs(size[0] * Math.cos(opt_rotation)) + Math.abs(size[1] * Math.sin(opt_rotation)); - size[1] = Math.abs(size[0] * Math.sin(opt_rotation)) + Math.abs(size[1] * Math.cos(opt_rotation)); + const w = size[0]; + const h = size[1]; + size[0] = Math.abs(w * Math.cos(opt_rotation)) + Math.abs(h * Math.sin(opt_rotation)); + size[1] = Math.abs(w * Math.sin(opt_rotation)) + Math.abs(h * Math.cos(opt_rotation)); } return size; } diff --git a/src/ol/interaction/Interaction.js b/src/ol/interaction/Interaction.js index 405e986891..b2897c8658 100644 --- a/src/ol/interaction/Interaction.js +++ b/src/ol/interaction/Interaction.js @@ -4,7 +4,6 @@ import BaseObject from '../Object.js'; import {easeOut, linear} from '../easing.js'; import InteractionProperty from './Property.js'; -import {clamp} from '../math.js'; /** @@ -194,7 +193,6 @@ export function zoom(view, resolution, opt_anchor, opt_duration, opt_direction) */ export function zoomByDelta(view, delta, opt_anchor, opt_duration) { const currentZoom = view.getZoom(); - const currentResolution = view.getResolution(); if (currentZoom === undefined) { return; @@ -203,21 +201,6 @@ export function zoomByDelta(view, delta, opt_anchor, opt_duration) { const newZoom = view.getValidZoomLevel(currentZoom + delta); const newResolution = view.getResolutionForZoom(newZoom); - // If we have a constraint on center, we need to change the anchor so that the - // new center is within the extent. We first calculate the new center, apply - // the constraint to it, and then calculate back the anchor - if (opt_anchor) { - const currentCenter = view.getCenter(); - const center = view.calculateCenterZoom(newResolution, opt_anchor); - - opt_anchor = [ - (newResolution * currentCenter[0] - currentResolution * center[0]) / - (newResolution - currentResolution), - (newResolution * currentCenter[1] - currentResolution * center[1]) / - (newResolution - currentResolution) - ]; - } - if (opt_duration > 0) { if (view.getAnimating()) { view.cancelAnimations(); diff --git a/test/spec/ol/interaction/interaction.test.js b/test/spec/ol/interaction/interaction.test.js index 3d2d04e91a..5a6f14a703 100644 --- a/test/spec/ol/interaction/interaction.test.js +++ b/test/spec/ol/interaction/interaction.test.js @@ -128,7 +128,7 @@ describe('ol.interaction.Interaction', function() { expect(view.getCenter()).to.eql([10, 10]); }); - it('changes view resolution and center relative to the anchor, while respecting the extent', function() { + it('changes view resolution and center relative to the anchor, while respecting the extent (center only)', function() { const view = new View({ center: [0, 0], extent: [-2.5, -2.5, 2.5, 2.5], @@ -149,6 +149,50 @@ describe('ol.interaction.Interaction', function() { zoomByDelta(view, -2, [0, 0]); expect(view.getCenter()).to.eql([2.5, 2.5]); }); + + it('changes view resolution and center relative to the anchor, while respecting the extent', function() { + const map = new Map({}); + const view = new View({ + center: [50, 50], + extent: [0, 0, 100, 100], + resolution: 1, + resolutions: [4, 2, 1, 0.5, 0.25, 0.125] + }); + map.setView(view); + + zoomByDelta(view, 1, [100, 100]); + expect(view.getCenter()).to.eql([75, 75]); + + zoomByDelta(view, -1, [75, 75]); + expect(view.getCenter()).to.eql([50, 50]); + + zoomByDelta(view, 2, [100, 100]); + expect(view.getCenter()).to.eql([87.5, 87.5]); + + zoomByDelta(view, -3, [0, 0]); + expect(view.getCenter()).to.eql([50, 50]); + expect(view.getResolution()).to.eql(2); + }); + + it('changes view resolution and center relative to the anchor, while respecting the extent (rotated)', function() { + const map = new Map({}); + const view = new View({ + center: [50, 50], + extent: [-100, -100, 100, 100], + resolution: 1, + resolutions: [2, 1, 0.5, 0.25, 0.125], + rotation: Math.PI / 4 + }); + map.setView(view); + const halfSize = 100 * Math.SQRT1_2; + + zoomByDelta(view, 1, [100, 100]); + expect(view.getCenter()).to.eql([100 - halfSize / 2, 100 - halfSize / 2]); + + view.setCenter([0, 50]); + zoomByDelta(view, -1, [0, 0]); + expect(view.getCenter()).to.eql([0, 100 - halfSize]); + }); }); }); diff --git a/test/spec/ol/view.test.js b/test/spec/ol/view.test.js index b41cc34f67..fcc5cd64d8 100644 --- a/test/spec/ol/view.test.js +++ b/test/spec/ol/view.test.js @@ -1269,8 +1269,14 @@ describe('ol.View', function() { document.body.removeChild(target); }); it('calculates the size correctly', function() { - const size = map.getView().getSizeFromViewport_(); + let size = map.getView().getSizeFromViewport_(); expect(size).to.eql([200, 150]); + size = map.getView().getSizeFromViewport_(Math.PI / 2); + expect(size[0]).to.roughlyEqual(150,1e-9); + expect(size[1]).to.roughlyEqual(200, 1e-9); + size = map.getView().getSizeFromViewport_(Math.PI); + expect(size[0]).to.roughlyEqual(200,1e-9); + expect(size[1]).to.roughlyEqual(150, 1e-9); }); });