From f0f1ea086753455ee883b2694eff9ea3f8976b05 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Mon, 17 Dec 2012 14:54:08 +0100 Subject: [PATCH 1/2] Skip frames when minimum frame rate is not reached The new minFrameRate option is used to make sure that an animation does not run longer than the time calculated from that frame rate. Time is made up by skipping frames, i.e. skipping execution of the eachStep callback. --- lib/OpenLayers/Tween.js | 22 +++++++++++++++++++++- tests/Tween.html | 30 ++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) 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'); + }); + } From 9759902daccdf2fd919a9b7f495b5e3d320eb391 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Fri, 21 Dec 2012 21:24:04 +0100 Subject: [PATCH 2/2] Fixing API; addressing @mpriour's doc comment Previously, minFrameRate could not be set as option with the start method. The tests failed to catch this flaw. Now both the start method and the tests are fixed. --- lib/OpenLayers/Tween.js | 14 ++++++++------ tests/Tween.html | 31 +++++++++++++++++-------------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/lib/OpenLayers/Tween.js b/lib/OpenLayers/Tween.js index 14e77210b8..eb2ee94e9d 100644 --- a/lib/OpenLayers/Tween.js +++ b/lib/OpenLayers/Tween.js @@ -54,12 +54,12 @@ OpenLayers.Tween = OpenLayers.Class({ /** * 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. + * {Number} The minimum framerate for animations in frames per second. 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. Default is 30. */ - minFrameRate: 30, + minFrameRate: null, /** * Property: startTime @@ -99,7 +99,8 @@ OpenLayers.Tween = OpenLayers.Class({ * begin - {Object} values to start the animation with * finish - {Object} values to finish the animation with * duration - {int} duration of the tween (number of steps) - * options - {Object} hash of options (for example callbacks (start, eachStep, done)) + * options - {Object} hash of options (callbacks (start, eachStep, done), + * minFrameRate) */ start: function(begin, finish, duration, options) { this.playing = true; @@ -107,6 +108,7 @@ OpenLayers.Tween = OpenLayers.Class({ this.finish = finish; this.duration = duration; this.callbacks = options.callbacks; + this.minFrameRate = options.minFrameRate || 30; this.time = 0; this.startTime = new Date().getTime(); OpenLayers.Animation.stop(this.animationId); diff --git a/tests/Tween.html b/tests/Tween.html index 5c52b84e26..1fbfa3cf1c 100644 --- a/tests/Tween.html +++ b/tests/Tween.html @@ -79,29 +79,32 @@ t.plan(2); var tween = new OpenLayers.Tween(); - var log1 = 0; + var log = 0; tween.start({count: 0}, {count: 10}, 10, { callbacks: { eachStep: function() { - log1++; + log++; } }, 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'); + t.eq(log, 0, 'all frames skipped at a frame rate of 10000'); + + log = 0; + tween.start({count: 0}, {count: 10}, 10, { + callbacks: { + eachStep: function() { + log++; + } + }, + minFrameRate: 1 + }); + }); + + t.delay_call(1.6, function() { + t.eq(log, 11, 'no frames skipped at a frame rate of 1'); }); }