animation fixed

This commit is contained in:
javi 2013-08-30 12:15:13 +02:00
parent e5a5102c6f
commit 5feac397bd
5 changed files with 92 additions and 63 deletions

View File

@ -26,31 +26,11 @@
maxDelta: 0.2, maxDelta: 0.2,
loop: true loop: true
}); });
this.domain = invLinear(this.options.animationDelay, this.options.animationDelay + this.options.animationDuration); this.domainInv = torque.math.linear(this.options.animationDelay, this.options.animationDelay + this.options.animationDuration);
this.range = linear(0, this.options.steps); this.domain = this.domainInv.invert();
} this.range = torque.math.linear(0, this.options.steps);
this.rangeInv = this.range.invert();
function clamp(a, b) {
return function(t) {
return Math.max(Math.min(t, b), a);
};
}
function invLinear(a, b) {
var c = clamp(0, 1.0);
return function(t) {
return c((t - a)/(b - a));
};
}
function linear(a, b) {
var c = clamp(a, b);
return function(t) {
return c(a*(1.0 - t) + t*b);
};
} }
@ -76,6 +56,11 @@
} }
}, },
step: function(s) {
if(arguments.length === 0) return this.range(this.domain(this._time));
this._time = this.domainInv(this.rangeInv(s));
},
pause: function() { pause: function() {
this.running = false; this.running = false;
cancelAnimationFrame(this._tick); cancelAnimationFrame(this._tick);
@ -86,7 +71,7 @@
var delta = (t1 - this._t0)*0.001; var delta = (t1 - this._t0)*0.001;
// if delta is really big means the tab lost the focus // if delta is really big means the tab lost the focus
// at some point, so limit delta change // at some point, so limit delta change
delta = Math.min(this.options.maxDelta, delta) delta = Math.min(this.options.maxDelta, delta);
this._t0 = t1; this._t0 = t1;
this._time += delta; this._time += delta;
var t = this.range(this.domain(this._time)); var t = this.range(this.domain(this._time));

View File

@ -6,6 +6,7 @@ function GMapsTorqueLayer(options) {
var self = this; var self = this;
this.key = 0; this.key = 0;
this.cartocss = null; this.cartocss = null;
this.ready = false;
this.options = _.extend({}, options); this.options = _.extend({}, options);
_.defaults(this.options, { _.defaults(this.options, {
provider: 'sql_api', provider: 'sql_api',
@ -40,8 +41,9 @@ function GMapsTorqueLayer(options) {
* torque layer * torque layer
*/ */
GMapsTorqueLayer.prototype = _.extend({}, GMapsTorqueLayer.prototype = _.extend({},
CanvasLayer.prototype, CanvasLayer.prototype,
torque.GMapsTileLoader.prototype, torque.GMapsTileLoader.prototype,
torque.Event,
{ {
providers: { providers: {
@ -94,17 +96,6 @@ GMapsTorqueLayer.prototype = _.extend({},
var canvas = this.canvas; var canvas = this.canvas;
canvas.width = canvas.width; canvas.width = canvas.width;
var ctx = canvas.getContext('2d'); var ctx = canvas.getContext('2d');
/*
ctx.fillStyle = 'white';
var offset = this._map.getProjection().fromLatLngToPoint(this.getTopLeft());
ctx.translate(-offset.x, -offset.y);
ctx.fillRect(0, 0, 100, 100);
var a = document.getElementsByTagName('img');
for(var i = 0; i < a.length; ++i) {
a[i].style.border = '1px solid red';
}
*/
// renders only a "frame" // renders only a "frame"
for(t in this._tiles) { for(t in this._tiles) {
@ -122,20 +113,44 @@ GMapsTorqueLayer.prototype = _.extend({},
*/ */
setKey: function(key) { setKey: function(key) {
this.key = key; this.key = key;
this.animator.step(key);
this.redraw(); this.redraw();
this.fire('change:time', { time: this.getTime(), step: this.key });
}, },
/** /**
* helper function, does the same than ``setKey`` but only * helper function, does the same than ``setKey`` but only
* accepts scalars. * accepts scalars.
*/ */
setTime: function(time) { setStep: function(time) {
if(time === undefined || time.length !== undefined) { if(time === undefined || time.length !== undefined) {
throw new Error("setTime only accept scalars"); throw new Error("setTime only accept scalars");
} }
this.setKey(time); this.setKey(time);
}, },
/**
* transform from animation step to Date object
* that contains the animation time
*
* ``step`` should be between 0 and ``steps - 1``
*/
stepToTime: function(step) {
if (!this.provider) return 0;
var times = this.provider.getKeySpan();
var time = times.start + (times.end - times.start)*(step/this.options.steps);
return new Date(time*1000);
},
/**
* returns the animation time defined by the data
* in the defined column. Date object
*/
getTime: function() {
return this.stepToTime(this.key);
},
/** /**
* set the cartocss for the current renderer * set the cartocss for the current renderer

View File

@ -44,16 +44,18 @@ L.Mixin.TileLoader = {
}, },
_removeOtherTiles: function (bounds) { _removeOtherTiles: function (bounds) {
var kArr, x, y, key; var kArr, x, y, z, key;
var zoom = this._map.getZoom();
for (key in this._tiles) { for (key in this._tiles) {
if (this._tiles.hasOwnProperty(key)) { if (this._tiles.hasOwnProperty(key)) {
kArr = key.split(':'); kArr = key.split(':');
x = parseInt(kArr[0], 10); x = parseInt(kArr[0], 10);
y = parseInt(kArr[1], 10); y = parseInt(kArr[1], 10);
z = parseInt(kArr[2], 10);
// remove tile if it's out of bounds // remove tile if it's out of bounds
if (x < bounds.min.x || x > bounds.max.x || y < bounds.min.y || y > bounds.max.y) { if (zoom !== z || x < bounds.min.x || x > bounds.max.x || y < bounds.min.y || y > bounds.max.y) {
this._removeTile(key); this._removeTile(key);
} }
} }

View File

@ -3,7 +3,6 @@
*/ */
L.TorqueLayer = L.CanvasLayer.extend({ L.TorqueLayer = L.CanvasLayer.extend({
providers: { providers: {
'sql_api': torque.providers.json, 'sql_api': torque.providers.json,
'url_template': torque.providers.jsonarray 'url_template': torque.providers.jsonarray
@ -61,23 +60,11 @@ L.TorqueLayer = L.CanvasLayer.extend({
canvas.width = canvas.width; canvas.width = canvas.width;
var ctx = canvas.getContext('2d'); var ctx = canvas.getContext('2d');
if(typeof this.key === 'number') { for(t in this._tiles) {
// renders only a "frame" tile = this._tiles[t];
for(t in this._tiles) { pos = this.getTilePos(tile.coord);
tile = this._tiles[t]; ctx.setTransform(1, 0, 0, 1, pos.x, pos.y);
pos = this.getTilePos(tile.coord); this.renderer.renderTile(tile, this.key, pos.x, pos.y);
ctx.setTransform(1, 0, 0, 1, pos.x, pos.y);
this.renderer.renderTile(tile, this.key, pos.x, pos.y);
}
} else {
// accumulate more than one
for(t in this._tiles) {
tile = this._tiles[t];
pos = this.getTilePos(tile.coord);
var accum = this.renderer.accumulate(tile, this.key);
ctx.setTransform(1, 0, 0, 1, pos.x, pos.y);
this.renderer.renderTileAccum(accum, 0, 0);
}
} }
}, },
@ -89,20 +76,48 @@ L.TorqueLayer = L.CanvasLayer.extend({
*/ */
setKey: function(key) { setKey: function(key) {
this.key = key; this.key = key;
this.animator.step(key);
this.redraw(); this.redraw();
this.fire('change:time', { time: this.getTime(), step: this.key });
}, },
/** /**
* helper function, does the same than ``setKey`` but only * helper function, does the same than ``setKey`` but only
* accepts scalars. * accepts scalars.
*/ */
setTime: function(time) { setStep: function(time) {
if(time === undefined || time.length !== undefined) { if(time === undefined || time.length !== undefined) {
throw new Error("setTime only accept scalars"); throw new Error("setTime only accept scalars");
} }
this.setKey(time); this.setKey(time);
}, },
/**
* transform from animation step to Date object
* that contains the animation time
*
* ``step`` should be between 0 and ``steps - 1``
*/
stepToTime: function(step) {
var times = this.provider.getKeySpan();
var time = times.start + (times.end - times.start)*(step/this.options.steps);
return new Date(time*1000);
},
/**
* returns the animation time defined by the data
* in the defined column. Date object
*/
getTime: function() {
return this.stepToTime(this.key);
},
/**
* returns an object with the start and end times
*/
getTimeSpan: function() {
var times = this.provider.getKeySpan();
},
/** /**
* set the cartocss for the current renderer * set the cartocss for the current renderer
@ -116,6 +131,8 @@ L.TorqueLayer = L.CanvasLayer.extend({
}); });
//_.extend(L.TorqueLayer.prototype, torque.Event);
L.TiledTorqueLayer = L.TileLayer.Canvas.extend({ L.TiledTorqueLayer = L.TileLayer.Canvas.extend({

View File

@ -25,7 +25,7 @@
if (options.resolution === undefined ) throw new Error("resolution should be provided"); if (options.resolution === undefined ) throw new Error("resolution should be provided");
if (options.steps === undefined ) throw new Error("steps should be provided"); if (options.steps === undefined ) throw new Error("steps should be provided");
if(options.start === undefined) { if(options.start === undefined) {
this.getKeySpan(); this._fetchKeySpan();
} else { } else {
this._ready = true; this._ready = true;
} }
@ -210,12 +210,21 @@
}); });
}, },
getKeySpan: function() {
return {
start: this.options.start,
end: this.options.end,
step: this.options.step,
steps: this.options.steps
};
},
// //
// the data range could be set by the user though ``start`` // the data range could be set by the user though ``start``
// option. It can be fecthed from the table when the start // option. It can be fecthed from the table when the start
// is not specified. // is not specified.
// //
getKeySpan: function() { _fetchKeySpan: function() {
var max_col, min_col, max_tmpl, min_tmpl; var max_col, min_col, max_tmpl, min_tmpl;
if (this.options.is_time){ if (this.options.is_time){
@ -233,13 +242,14 @@
max_col: max_col, max_col: max_col,
min_col: min_col, min_col: min_col,
table: this.options.table table: this.options.table
}) });
var self = this; var self = this;
this.sql(sql, function(data) { this.sql(sql, function(data) {
//TODO: manage bounds //TODO: manage bounds
data = data.rows[0]; data = data.rows[0];
self.options.start = data.min; self.options.start = data.min;
self.options.end = data.max;
self.options.step = (data.max - data.min)/self.options.steps; self.options.step = (data.max - data.min)/self.options.steps;
self._setReady(true); self._setReady(true);
}, { parseJSON: true }); }, { parseJSON: true });
@ -247,7 +257,7 @@
}; };
torque.providers.json = json torque.providers.json = json;
})(typeof exports === "undefined" ? this : exports); })(typeof exports === "undefined" ? this : exports);