diff --git a/src/ol/typedefs.js b/src/ol/typedefs.js index 95255c5d75..86f7d2927c 100644 --- a/src/ol/typedefs.js +++ b/src/ol/typedefs.js @@ -665,6 +665,7 @@ ol.TransformFunction; * rotationAnchor: (ol.Coordinate|undefined), * start: number, * duration: number, + * done: boolean, * easing: function(number):number, * callback: (function(boolean)|undefined) * }} diff --git a/src/ol/view.js b/src/ol/view.js index 8789964bb4..961bc9a6cd 100644 --- a/src/ol/view.js +++ b/src/ol/view.js @@ -202,6 +202,7 @@ ol.View.prototype.animate = function(var_args) { var animation = /** @type {ol.ViewAnimation} */ ({ start: start, + done: false, duration: options.duration || 1000, easing: options.easing || ol.easing.inAndOut }); @@ -278,16 +279,21 @@ ol.View.prototype.updateAnimations_ = function() { var more = false; for (var i = this.animations_.length - 1; i >= 0; --i) { var series = this.animations_[i]; - var animation; + var seriesDone = true; for (var j = 0, jj = series.length; j < jj; ++j) { - var candidate = series[i]; - if (candidate.duration > now - candidate.start) { - animation = candidate; - break; + var animation = series[j]; + if (animation.done) { + continue; } - } - if (animation) { - var progress = animation.easing((now - animation.start) / animation.duration); + var elapsed = now - animation.start; + var fraction = elapsed / animation.duration; + if (fraction > 1) { + animation.done = true; + fraction = 1; + } else { + seriesDone = false; + } + var progress = animation.easing(fraction); if (animation.sourceCenter) { var x0 = animation.sourceCenter[0]; var y0 = animation.sourceCenter[1]; @@ -313,11 +319,16 @@ ol.View.prototype.updateAnimations_ = function() { } } more = true; - } else { - this.animations_.pop(); + } + if (seriesDone) { + var completed = this.animations_.pop(); if (this.animations_.length === 0) { this.animating_ = false; } + var callback = completed[0].callback; + if (callback) { + callback(true); + } } } if (more && this.updateAnimationKey_ === undefined) { diff --git a/test/spec/ol/view.test.js b/test/spec/ol/view.test.js index 2d32a12adb..8affac3187 100644 --- a/test/spec/ol/view.test.js +++ b/test/spec/ol/view.test.js @@ -301,6 +301,48 @@ describe('ol.View', function() { }); + describe('#animate()', function() { + + var originalRequestAnimationFrame = window.requestAnimationFrame; + var originalCancelAnimationFrame = window.cancelAnimationFrame; + + beforeEach(function() { + window.requestAnimationFrame = function(callback) { + return setTimeout(callback, 1); + }; + window.cancelAnimationFrame = function(key) { + return clearTimeout(key); + }; + }); + + afterEach(function() { + window.requestAnimationFrame = originalRequestAnimationFrame; + window.cancelAnimationFrame = originalCancelAnimationFrame; + }); + + it('can be called to animate view properties', function(done) { + var view = new ol.View({ + center: [0, 0], + zoom: 5 + }); + + view.animate({ + zoom: 4, + duration: 25 + }); + expect(view.getAnimating()).to.eql(true); + + setTimeout(function() { + expect(view.getCenter()).to.eql([0, 0]); + expect(view.getZoom()).to.eql(4); + expect(view.getAnimating()).to.eql(false); + done(); + }, 50); + + }); + + }); + describe('#getResolutions', function() { var view; var resolutions = [512, 256, 128, 64, 32, 16];