diff --git a/lib/OpenLayers/Tween.js b/lib/OpenLayers/Tween.js index 4e504381a5..14e77210b8 100644 --- a/lib/OpenLayers/Tween.js +++ b/lib/OpenLayers/Tween.js @@ -52,6 +52,22 @@ OpenLayers.Tween = OpenLayers.Class({ */ time: null, + /** + * APIProperty: minFrameRate + * {Number} The minimum framerate for animations. After each step, the time + * spent in the animation is compared to the calculated time at this frame + * rate. If the animation runs longer than the calculated time, the next + * step is skipped. + */ + minFrameRate: 30, + + /** + * Property: startTime + * {Number} The timestamp of the first execution step. Used for skipping + * frames + */ + startTime: null, + /** * Property: animationId * {int} Loop id returned by OpenLayers.Animation.start @@ -92,6 +108,7 @@ OpenLayers.Tween = OpenLayers.Class({ this.duration = duration; this.callbacks = options.callbacks; this.time = 0; + this.startTime = new Date().getTime(); OpenLayers.Animation.stop(this.animationId); this.animationId = null; if (this.callbacks && this.callbacks.start) { @@ -139,7 +156,10 @@ OpenLayers.Tween = OpenLayers.Class({ this.time++; if (this.callbacks && this.callbacks.eachStep) { - this.callbacks.eachStep.call(this, value); + // skip frames if frame rate drops below threshold + if ((new Date().getTime() - this.startTime) / this.time <= 1000 / this.minFrameRate) { + this.callbacks.eachStep.call(this, value); + } } if (this.time > this.duration) { diff --git a/tests/Tween.html b/tests/Tween.html index fdd8fa7016..5c52b84e26 100644 --- a/tests/Tween.html +++ b/tests/Tween.html @@ -74,6 +74,36 @@ tween.stop(); t.ok(tween.animationId != null, "stop method doesn't do anything if tween isn't running"); } + + function test_Tween_skip(t) { + t.plan(2); + + var tween = new OpenLayers.Tween(); + var log1 = 0; + tween.start({count: 0}, {count: 10}, 10, { + callbacks: { + eachStep: function() { + log1++; + } + }, + minFrameRate: 10000 + }); + + var log2 = 0; + tween.start({count: 0}, {count: 10}, 10, { + callbacks: { + eachStep: function() { + log2++; + } + }, + minFrameRate: 1 + }); + + t.delay_call(0.8, function() { + t.eq(log1, 0, 'all frames skipped at a frame rate of 10000'); + t.eq(log2, 11, 'no frames skipped at a frame rate of 1'); + }); + }