From 48178f0e31c9e67a53be29d1c8b8308bc2dee4ea Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Mon, 14 Aug 2017 08:47:29 -0400 Subject: [PATCH] Immediately complete no-op animations --- src/ol/view.js | 33 +++++++++++- test/spec/ol/view.test.js | 104 +++++++++++++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 3 deletions(-) diff --git a/src/ol/view.js b/src/ol/view.js index 4b818ff955..4f5e6d33ee 100644 --- a/src/ol/view.js +++ b/src/ol/view.js @@ -302,7 +302,14 @@ ol.View.prototype.animate = function(var_args) { } animation.callback = callback; - start += animation.duration; + + // check if animation is a no-op + if (ol.View.isNoopAnimation(animation)) { + animation.complete = true; + // we still push it onto the series for callback handling + } else { + start += animation.duration; + } series.push(animation); } this.animations_.push(series); @@ -1158,3 +1165,27 @@ ol.View.createRotationConstraint_ = function(options) { return ol.RotationConstraint.disable; } }; + + +/** + * Determine if an animation involves no view change. + * @param {ol.ViewAnimation} animation The animation. + * @return {boolean} The animation involves no view change. + */ +ol.View.isNoopAnimation = function(animation) { + if (animation.sourceCenter) { + if (animation.sourceCenter[0] !== animation.targetCenter[0]) { + return false; + } + if (animation.sourceCenter[1] !== animation.targetCenter[1]) { + return false; + } + } + if (animation.sourceResolution !== animation.targetResolution) { + return false; + } + if (animation.sourceRotation !== animation.targetRotation) { + return false; + } + return true; +}; diff --git a/test/spec/ol/view.test.js b/test/spec/ol/view.test.js index 94402b7fd1..889e382a87 100644 --- a/test/spec/ol/view.test.js +++ b/test/spec/ol/view.test.js @@ -457,6 +457,20 @@ describe('ol.View', function() { }, 10); }); + it('immediately completes for no-op animations', function() { + var view = new ol.View({ + center: [0, 0], + zoom: 5 + }); + + view.animate({ + zoom: 5, + center: [0, 0], + duration: 25 + }); + expect(view.getAnimating()).to.eql(false); + }); + it('prefers zoom over resolution', function(done) { var view = new ol.View({ center: [0, 0], @@ -556,6 +570,21 @@ describe('ol.View', function() { view.setCenter([1, 2]); // interrupt the animation }); + it('calls a callback even if animation is a no-op', function(done) { + var view = new ol.View({ + center: [0, 0], + zoom: 0 + }); + + view.animate({ + zoom: 0, + duration: 25 + }, function(complete) { + expect(complete).to.be(true); + done(); + }); + }); + it('can run multiple animations in series', function(done) { var view = new ol.View({ center: [0, 0], @@ -613,7 +642,7 @@ describe('ol.View', function() { expect(view.getHints()[ol.ViewHint.ANIMATING]).to.be(2); view.animate({ - rotate: Math.PI, + rotation: Math.PI, duration: 25 }, decrement); expect(view.getHints()[ol.ViewHint.ANIMATING]).to.be(3); @@ -640,7 +669,7 @@ describe('ol.View', function() { expect(view.getHints()[ol.ViewHint.ANIMATING]).to.be(2); view.animate({ - rotate: Math.PI, + rotation: Math.PI, duration: 25 }); expect(view.getHints()[ol.ViewHint.ANIMATING]).to.be(3); @@ -1282,3 +1311,74 @@ describe('ol.View', function() { }); }); }); + +describe('ol.View.isNoopAnimation()', function() { + + var cases = [{ + animation: { + sourceCenter: [0, 0], targetCenter: [0, 0], + sourceResolution: 1, targetResolution: 1, + sourceRotation: 0, targetRotation: 0 + }, + noop: true + }, { + animation: { + sourceCenter: [0, 0], targetCenter: [0, 1], + sourceResolution: 1, targetResolution: 1, + sourceRotation: 0, targetRotation: 0 + }, + noop: false + }, { + animation: { + sourceCenter: [0, 0], targetCenter: [0, 0], + sourceResolution: 1, targetResolution: 0, + sourceRotation: 0, targetRotation: 0 + }, + noop: false + }, { + animation: { + sourceCenter: [0, 0], targetCenter: [0, 0], + sourceResolution: 1, targetResolution: 1, + sourceRotation: 0, targetRotation: 1 + }, + noop: false + }, { + animation: { + sourceCenter: [0, 0], targetCenter: [0, 0] + }, + noop: true + }, { + animation: { + sourceCenter: [1, 0], targetCenter: [0, 0] + }, + noop: false + }, { + animation: { + sourceResolution: 1, targetResolution: 1 + }, + noop: true + }, { + animation: { + sourceResolution: 0, targetResolution: 1 + }, + noop: false + }, { + animation: { + sourceRotation: 10, targetRotation: 10 + }, + noop: true + }, { + animation: { + sourceRotation: 0, targetRotation: 10 + }, + noop: false + }]; + + cases.forEach(function(c, i) { + it('works for case ' + i, function() { + var noop = ol.View.isNoopAnimation(c.animation); + expect(noop).to.equal(c.noop); + }); + }); + +});