Implement possibility to set and remove a steps range
This commit is contained in:
parent
6f35d6399a
commit
b6169fb31a
4
Makefile
4
Makefile
@ -7,7 +7,7 @@ JS_CLIENT_FILES= lib/torque/*.js \
|
||||
lib/torque/gmaps/*.js \
|
||||
lib/torque/leaflet/leaflet_tileloader_mixin.js \
|
||||
lib/torque/leaflet/canvas_layer.js \
|
||||
lib/torque/leaflet/torque.js
|
||||
lib/torque/leaflet/torque.js
|
||||
|
||||
all: dist/torque.js dist/torque.full.js add-header
|
||||
|
||||
@ -47,7 +47,7 @@ test-acceptance: clean-results
|
||||
|
||||
test-all: test test-acceptance
|
||||
|
||||
clean:
|
||||
clean:
|
||||
rm -rf dist
|
||||
|
||||
.PHONY: clean dist_folder
|
||||
|
24
lib/torque/animator-steps-range.js
Normal file
24
lib/torque/animator-steps-range.js
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Abstract handler for animator steps
|
||||
*/
|
||||
var AnimatorStepsRange = function(start, end) {
|
||||
if (start < 0) throw new Error('start must be a positive number');
|
||||
if (start >= end) throw new Error('start must be smaller than end');
|
||||
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
};
|
||||
|
||||
AnimatorStepsRange.prototype = {
|
||||
|
||||
diff: function() {
|
||||
return this.end - this.start;
|
||||
},
|
||||
|
||||
isLast: function(step) {
|
||||
// round step into an integer, to be able to compare number as expected (also converts bad input to 0)
|
||||
return (step | 0) === this.end;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = AnimatorStepsRange;
|
@ -1,4 +1,5 @@
|
||||
var torque = require('./');
|
||||
var StepsRange = require('./animator-steps-range');
|
||||
|
||||
var requestAnimationFrame = global.requestAnimationFrame
|
||||
|| global.mozRequestAnimationFrame
|
||||
@ -35,18 +36,16 @@ var cancelAnimationFrame = global.cancelAnimationFrame
|
||||
loop: options.loop === undefined ? true : options.loop
|
||||
}, this.options);
|
||||
|
||||
this.rescale();
|
||||
|
||||
this.steps(options.steps);
|
||||
}
|
||||
|
||||
|
||||
Animator.prototype = {
|
||||
|
||||
start: function() {
|
||||
this.running = true;
|
||||
requestAnimationFrame(this._tick);
|
||||
this.options.onStart && this.options.onStart();
|
||||
if(this.options.steps === 1){
|
||||
if (this.stepsRange().diff() === 1) {
|
||||
this.running = false;
|
||||
}
|
||||
},
|
||||
@ -57,7 +56,7 @@ var cancelAnimationFrame = global.cancelAnimationFrame
|
||||
|
||||
stop: function() {
|
||||
this.pause();
|
||||
this.time(0);
|
||||
this.time(this.stepsRange().start);
|
||||
this.options.onStop && this.options.onStop();
|
||||
},
|
||||
|
||||
@ -80,7 +79,7 @@ var cancelAnimationFrame = global.cancelAnimationFrame
|
||||
rescale: function() {
|
||||
this.domainInv = torque.math.linear(this.options.animationDelay, this.options.animationDelay + this.options.animationDuration);
|
||||
this.domain = this.domainInv.invert();
|
||||
this.range = torque.math.linear(0, this.options.steps);
|
||||
this.range = torque.math.linear(0, this._defaultStepsRange.end);
|
||||
this.rangeInv = this.range.invert();
|
||||
this.time(this._time);
|
||||
this.running? this.start(): this.pause();
|
||||
@ -99,9 +98,34 @@ var cancelAnimationFrame = global.cancelAnimationFrame
|
||||
|
||||
steps: function(_) {
|
||||
this.options.steps = _;
|
||||
this._defaultStepsRange = new StepsRange(0, _);
|
||||
return this.rescale();
|
||||
},
|
||||
|
||||
// Returns or sets a (custom) steps range
|
||||
// Setting a steps range must be within the full range
|
||||
stepsRange: function(start, end) {
|
||||
if (arguments.length === 2) {
|
||||
if (start < this._defaultStepsRange.start) throw new Error('start must be within default steps range');
|
||||
if (end > this._defaultStepsRange.end) throw new Error('end must be within default steps range');
|
||||
|
||||
this._customStepsRange = new StepsRange(start, end);
|
||||
this.options.onStepsRange && this.options.onStepsRange();
|
||||
|
||||
// Change current step if it's outside the new custom range
|
||||
var step = this.step() | 0; // round to an integer
|
||||
if (step < start || step > end) {
|
||||
this.step(start);
|
||||
}
|
||||
}
|
||||
return this._customStepsRange || this._defaultStepsRange;
|
||||
},
|
||||
|
||||
removeCustomStepsRange: function() {
|
||||
this._customStepsRange = undefined;
|
||||
this.options.onStepsRange && this.options.onStepsRange();
|
||||
},
|
||||
|
||||
step: function(s) {
|
||||
if(arguments.length === 0) return this.range(this.domain(this._time));
|
||||
this._time = this.domainInv(this.rangeInv(s));
|
||||
@ -121,13 +145,15 @@ var cancelAnimationFrame = global.cancelAnimationFrame
|
||||
delta = Math.min(this.options.maxDelta, delta);
|
||||
this._t0 = t1;
|
||||
this._time += delta;
|
||||
if(this.step() >= this.options.steps) {
|
||||
|
||||
var stepsRange = this.stepsRange();
|
||||
if (stepsRange.isLast(this.step())) {
|
||||
if(!this.options.loop){
|
||||
// set time to max time
|
||||
this.time(this.options.animationDuration);
|
||||
this.pause();
|
||||
} else {
|
||||
this._time = 0;
|
||||
this.step(stepsRange.start);
|
||||
}
|
||||
}
|
||||
if(this.running) {
|
||||
|
@ -43,6 +43,9 @@ function GMapsTorqueLayer(options) {
|
||||
},
|
||||
onStart: function() {
|
||||
self.fire('play');
|
||||
},
|
||||
onStepsRange: function() {
|
||||
self.fire('change:stepsRange', self.animator.stepsRange());
|
||||
}
|
||||
}));
|
||||
|
||||
@ -237,7 +240,7 @@ GMapsTorqueLayer.prototype = torque.extend({},
|
||||
},
|
||||
|
||||
/**
|
||||
* helper function, does the same than ``setKey`` but only
|
||||
* helper function, does the same than ``setKey`` but only
|
||||
* accepts scalars.
|
||||
*/
|
||||
setStep: function(time) {
|
||||
@ -248,10 +251,10 @@ GMapsTorqueLayer.prototype = torque.extend({},
|
||||
},
|
||||
|
||||
/**
|
||||
* transform from animation step to Date object
|
||||
* transform from animation step to Date object
|
||||
* that contains the animation time
|
||||
*
|
||||
* ``step`` should be between 0 and ``steps - 1``
|
||||
* ``step`` should be between 0 and ``steps - 1``
|
||||
*/
|
||||
stepToTime: function(step) {
|
||||
if (!this.provider) return 0;
|
||||
@ -369,7 +372,7 @@ GMapsTorqueLayer.prototype = torque.extend({},
|
||||
}
|
||||
return sum;
|
||||
},
|
||||
|
||||
|
||||
error: function (callback) {
|
||||
this.options.errorCallback = callback;
|
||||
return this;
|
||||
@ -450,6 +453,18 @@ GMapsTiledTorqueLayer.prototype = torque.extend({}, CanvasTileLayer.prototype, {
|
||||
setCartoCSS: function(cartocss) {
|
||||
if (!this.renderer) throw new Error('renderer is not valid');
|
||||
return this.renderer.setCartoCSS(cartocss);
|
||||
},
|
||||
|
||||
setStepsRange: function(start, end) {
|
||||
this.animator.stepsRange(start, end);
|
||||
},
|
||||
|
||||
removeStepsRange: function() {
|
||||
this.animator.removeCustomStepsRange();
|
||||
},
|
||||
|
||||
getStepsRange: function() {
|
||||
return this.animator.stepsRange();
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -51,6 +51,9 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
},
|
||||
onStart: function() {
|
||||
self.fire('play');
|
||||
},
|
||||
onStepsRange: function() {
|
||||
self.fire('change:stepsRange', self.animator.stepsRange());
|
||||
}
|
||||
}));
|
||||
|
||||
@ -428,5 +431,17 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
|
||||
invalidate: function() {
|
||||
this.provider.reload();
|
||||
},
|
||||
|
||||
setStepsRange: function(start, end) {
|
||||
this.animator.stepsRange(start, end);
|
||||
},
|
||||
|
||||
removeStepsRange: function() {
|
||||
this.animator.removeCustomStepsRange();
|
||||
},
|
||||
|
||||
getStepsRange: function() {
|
||||
return this.animator.stepsRange();
|
||||
}
|
||||
});
|
||||
|
34
test/animator-steps-range.js
Normal file
34
test/animator-steps-range.js
Normal file
@ -0,0 +1,34 @@
|
||||
var AnimatorStepsRange = require('../lib/torque/animator-steps-range');
|
||||
|
||||
QUnit.module('animator-steps-range');
|
||||
|
||||
test('start and end props are available', function(assert) {
|
||||
var stepsRange = validStepsRange();
|
||||
assert.equal(stepsRange.start, 0);
|
||||
assert.equal(stepsRange.end, 4);
|
||||
});
|
||||
|
||||
test('.lastStep returns true if given last step', function(assert) {
|
||||
var stepsRange = validStepsRange();
|
||||
assert.ok(stepsRange.isLast(stepsRange.end));
|
||||
|
||||
assert.notOk(stepsRange.isLast(3));
|
||||
assert.notOk(stepsRange.isLast(42));
|
||||
assert.notOk(stepsRange.isLast(true));
|
||||
assert.notOk(stepsRange.isLast());
|
||||
assert.notOk(stepsRange.isLast('whatever'));
|
||||
});
|
||||
|
||||
test('.diff returns the steps between start and end', function(assert) {
|
||||
var stepsRange = validStepsRange();
|
||||
assert.equal(stepsRange.diff(), 4);
|
||||
});
|
||||
|
||||
test('throws error in inconsistent range', function(assert) {
|
||||
assert.throws(function() { new AnimatorStepsRange(4, 3) });
|
||||
assert.throws(function() { new AnimatorStepsRange(4, 4) });
|
||||
});
|
||||
|
||||
function validStepsRange() {
|
||||
return new AnimatorStepsRange(0, 4);
|
||||
}
|
@ -39,12 +39,66 @@ test("onStart runs properly", function(assert){
|
||||
animator.stop();
|
||||
});
|
||||
|
||||
test("stop should take the pointer to position zero", function(assert){
|
||||
test(".stepsRange sets a custom range with valid input", function(assert){
|
||||
var animator = new torque.Animator(function(){}, {steps: 500, animationDuration: 2});
|
||||
var customStepsRange = animator.stepsRange(101, 202);
|
||||
assert.ok(customStepsRange);
|
||||
assert.equal(customStepsRange.start, 101);
|
||||
assert.equal(customStepsRange.end, 202);
|
||||
|
||||
var didCallOnStepsRange = false;
|
||||
var animator = new torque.Animator(function(){}, {steps: 500, animationDuration: 2,
|
||||
onStepsRange: function() {
|
||||
didCallOnStepsRange = true;
|
||||
}
|
||||
});
|
||||
animator.stepsRange(101, 202);
|
||||
assert.ok(didCallOnStepsRange);
|
||||
});
|
||||
|
||||
test(".stepsRange throws error if given range is outside default range", function(assert){
|
||||
var animator = new torque.Animator(function(){}, {steps: 500, animationDuration: 2});
|
||||
assert.throws(function() { animator.stepsRange(1, 501) });
|
||||
assert.throws(function() { animator.stepsRange(-1, 500) });
|
||||
assert.throws(function() { animator.stepsRange(-1, 9000) });
|
||||
});
|
||||
|
||||
test(".removeCustomStepsRange should remove any custom steps range", function(assert){
|
||||
var animator = new torque.Animator(function(){}, {steps: 500, animationDuration: 2});
|
||||
animator.removeCustomStepsRange();
|
||||
animator.stepsRange(101, 202);
|
||||
var customStepsRange = animator.stepsRange();
|
||||
animator.removeCustomStepsRange();
|
||||
var defaultStepsRange = animator.stepsRange();
|
||||
assert.ok(defaultStepsRange);
|
||||
assert.notEqual(defaultStepsRange, customStepsRange);
|
||||
assert.equal(defaultStepsRange.start, 0);
|
||||
assert.equal(defaultStepsRange.end, 500);
|
||||
|
||||
var didCallOnStepsRange = false;
|
||||
var animator = new torque.Animator(function(){}, {steps: 500, animationDuration: 2,
|
||||
onStepsRange: function() {
|
||||
didCallOnStepsRange = true;
|
||||
}
|
||||
});
|
||||
animator.stepsRange(101, 202);
|
||||
animator.removeCustomStepsRange();
|
||||
assert.ok(didCallOnStepsRange);
|
||||
});
|
||||
|
||||
test("stop should take the pointer to position zero by default", function(assert){
|
||||
var animator = new torque.Animator(function(){}, {steps: 500, animationDuration: 2});
|
||||
animator.stop()
|
||||
assert.equal(animator._time, 0);
|
||||
});
|
||||
|
||||
test("stop should take the pointer to start position for custom range", function(assert){
|
||||
var animator = new torque.Animator(function(){}, {steps: 500, animationDuration: 2});
|
||||
animator.stepsRange(42, 137);
|
||||
animator.stop()
|
||||
assert.equal(animator._time, 42);
|
||||
});
|
||||
|
||||
test("stop should call onStop", function(assert){
|
||||
var animator = new torque.Animator(function(){}, {steps: 500, animationDuration: 2});
|
||||
animator.options.onStop = function(){
|
||||
@ -61,14 +115,29 @@ test("altering steps should rescale", function(assert){
|
||||
assert.ok(animator.rescale.calledOnce);
|
||||
});
|
||||
|
||||
test("tick should set time to zero if steps are bigger than range", function(assert){
|
||||
test("tick should set time to zero if steps are bigger than default range", function(assert){
|
||||
var done = assert.async();
|
||||
var animatorb = new torque.Animator(function(){}, {steps: 500, animationDuration: 2});
|
||||
animatorb.start();
|
||||
animatorb.step(800);
|
||||
setTimeout(function(){
|
||||
console.log(animatorb.step());
|
||||
assert.ok(animatorb.step() < 800);
|
||||
assert.ok(animatorb.step() | 0 === 0);
|
||||
done();
|
||||
}, 20);
|
||||
animatorb.pause();
|
||||
});
|
||||
|
||||
test("tick should set time to start step if steps are bigger than custom range", function(assert){
|
||||
var done = assert.async();
|
||||
var animatorb = new torque.Animator(function(){}, {steps: 500, animationDuration: 2});
|
||||
animatorb.start();
|
||||
animatorb.step(800);
|
||||
animatorb.stepsRange(42, 137);
|
||||
setTimeout(function(){
|
||||
console.log(animatorb.step());
|
||||
// round step to an integer
|
||||
assert.ok(animatorb.step() | 0 === 42);
|
||||
done();
|
||||
}, 20);
|
||||
animatorb.pause();
|
||||
@ -80,5 +149,4 @@ test("tick should pause animation on end if loop is disabled", function(assert){
|
||||
animator.toggle();
|
||||
animator.step(600);
|
||||
assert.equal(animator._time,animator.options.animationDuration);
|
||||
|
||||
});
|
||||
|
@ -9,3 +9,4 @@ require('./provider.windshaft.test');
|
||||
require('./provider.json');
|
||||
require('./request');
|
||||
require('./animator');
|
||||
require('./animator-steps-range');
|
||||
|
Loading…
Reference in New Issue
Block a user