diff --git a/src/ol/interaction/interaction.js b/src/ol/interaction/interaction.js index 6ce00e740e..ffe39ca86b 100644 --- a/src/ol/interaction/interaction.js +++ b/src/ol/interaction/interaction.js @@ -180,6 +180,23 @@ ol.interaction.Interaction.zoom = function(view, resolution, opt_anchor, opt_dur ol.interaction.Interaction.zoomByDelta = function(view, delta, opt_anchor, opt_duration) { var currentResolution = view.getResolution(); var resolution = view.constrainResolution(currentResolution, delta, 0); + + // 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 && resolution !== undefined && resolution !== currentResolution) { + var currentCenter = view.getCenter(); + var center = view.calculateCenterZoom(resolution, opt_anchor); + center = view.constrainCenter(center); + + opt_anchor = [ + (resolution * currentCenter[0] - currentResolution * center[0]) / + (resolution - currentResolution), + (resolution * currentCenter[1] - currentResolution * center[1]) / + (resolution - currentResolution) + ]; + } + ol.interaction.Interaction.zoomWithoutConstraints( view, resolution, opt_anchor, opt_duration); }; diff --git a/src/ol/interaction/mousewheelzoom.js b/src/ol/interaction/mousewheelzoom.js index 98039aa36e..c4ca25b3fc 100644 --- a/src/ol/interaction/mousewheelzoom.js +++ b/src/ol/interaction/mousewheelzoom.js @@ -183,7 +183,7 @@ ol.interaction.MouseWheelZoom.handleEvent = function(mapBrowserEvent) { } if (this.lastAnchor_) { var center = view.calculateCenterZoom(resolution, this.lastAnchor_); - view.setCenter(center); + view.setCenter(view.constrainCenter(center)); } view.setResolution(resolution); if (rebound > 0) { diff --git a/test/spec/ol/interaction/interaction.test.js b/test/spec/ol/interaction/interaction.test.js index 7c38d9a29f..b9cbf62e01 100644 --- a/test/spec/ol/interaction/interaction.test.js +++ b/test/spec/ol/interaction/interaction.test.js @@ -58,4 +58,67 @@ describe('ol.interaction.Interaction', function() { }); + describe('zoomByDelta()', function() { + + it('changes view resolution', function() { + var view = new ol.View({ + resolution: 1, + resolutions: [4, 2, 1, 0.5, 0.25] + }); + + ol.interaction.Interaction.zoomByDelta(view, 1); + expect(view.getResolution()).to.be(0.5); + + ol.interaction.Interaction.zoomByDelta(view, -1); + expect(view.getResolution()).to.be(1); + + ol.interaction.Interaction.zoomByDelta(view, 2); + expect(view.getResolution()).to.be(0.25); + + ol.interaction.Interaction.zoomByDelta(view, -2); + expect(view.getResolution()).to.be(1); + }); + + it('changes view resolution and center relative to the anchor', function() { + var view = new ol.View({ + center: [0, 0], + resolution: 1, + resolutions: [4, 2, 1, 0.5, 0.25] + }); + + ol.interaction.Interaction.zoomByDelta(view, 1, [10, 10]); + expect(view.getCenter()).to.eql([5, 5]); + + ol.interaction.Interaction.zoomByDelta(view, -1, [0, 0]); + expect(view.getCenter()).to.eql([10, 10]); + + ol.interaction.Interaction.zoomByDelta(view, 2, [0, 0]); + expect(view.getCenter()).to.eql([2.5, 2.5]); + + ol.interaction.Interaction.zoomByDelta(view, -2, [0, 0]); + expect(view.getCenter()).to.eql([10, 10]); + }); + + it('changes view resolution and center relative to the anchor, while respecting the extent', function() { + var view = new ol.View({ + center: [0, 0], + extent: [-2.5, -2.5, 2.5, 2.5], + resolution: 1, + resolutions: [4, 2, 1, 0.5, 0.25] + }); + + ol.interaction.Interaction.zoomByDelta(view, 1, [10, 10]); + expect(view.getCenter()).to.eql([2.5, 2.5]); + + ol.interaction.Interaction.zoomByDelta(view, -1, [0, 0]); + expect(view.getCenter()).to.eql([2.5, 2.5]); + + ol.interaction.Interaction.zoomByDelta(view, 2, [10, 10]); + expect(view.getCenter()).to.eql([2.5, 2.5]); + + ol.interaction.Interaction.zoomByDelta(view, -2, [0, 0]); + expect(view.getCenter()).to.eql([2.5, 2.5]); + }); + }); + });