Compare commits
2 Commits
master
...
animation_
Author | SHA1 | Date | |
---|---|---|---|
|
fe27c0b515 | ||
|
589a29acfb |
@ -37,6 +37,7 @@
|
||||
start: function() {
|
||||
this.running = true;
|
||||
requestAnimationFrame(this._tick);
|
||||
this.options.onStart && this.options.onStart();
|
||||
},
|
||||
|
||||
isRunning: function() {
|
||||
@ -46,6 +47,7 @@
|
||||
stop: function() {
|
||||
this.pause();
|
||||
this.time(0);
|
||||
this.options.onStop && this.options.onStop();
|
||||
},
|
||||
|
||||
// real animation time
|
||||
@ -96,6 +98,7 @@
|
||||
pause: function() {
|
||||
this.running = false;
|
||||
cancelAnimationFrame(this._tick);
|
||||
this.options.onPause && this.options.onPause();
|
||||
},
|
||||
|
||||
_tick: function() {
|
||||
|
@ -37,7 +37,17 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
if(self.key !== k) {
|
||||
self.setKey(k, { direct: true });
|
||||
}
|
||||
}, torque.clone(options));
|
||||
}, torque.extend(torque.clone(options), {
|
||||
onPause: function() {
|
||||
self.fire('pause');
|
||||
},
|
||||
onStop: function() {
|
||||
self.fire('stop');
|
||||
},
|
||||
onStart: function() {
|
||||
self.fire('play');
|
||||
}
|
||||
}));
|
||||
|
||||
this.play = this.animator.start.bind(this.animator);
|
||||
this.stop = this.animator.stop.bind(this.animator);
|
||||
|
286
lib/torque/provider.template.js
Normal file
286
lib/torque/provider.template.js
Normal file
@ -0,0 +1,286 @@
|
||||
(function(exports) {
|
||||
|
||||
var torque = exports.torque = exports.torque || {};
|
||||
var providers = exports.torque.providers = exports.torque.providers || {};
|
||||
|
||||
var Uint8Array = torque.types.Uint8Array;
|
||||
var Int32Array = torque.types.Int32Array;
|
||||
var Uint32Array = torque.types.Uint32Array;
|
||||
|
||||
// format('hello, {0}', 'rambo') -> "hello, rambo"
|
||||
function format(str) {
|
||||
for(var i = 1; i < arguments.length; ++i) {
|
||||
var attrs = arguments[i];
|
||||
for(var attr in attrs) {
|
||||
str = str.replace(RegExp('\\{' + attr + '\\}', 'g'), attrs[attr]);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
var json = function (options) {
|
||||
this.options = options;
|
||||
|
||||
this.options.tiler_protocol = options.tiler_protocol || 'http';
|
||||
this.options.tiler_domain = options.tiler_domain || 'cartodb.com';
|
||||
this.options.tiler_port = options.tiler_port || 80;
|
||||
|
||||
|
||||
// check options
|
||||
if (options.resolution === undefined ) throw new Error("resolution should be provided");
|
||||
if (options.steps === undefined ) throw new Error("steps should be provided");
|
||||
};
|
||||
|
||||
json.prototype = {
|
||||
|
||||
/**
|
||||
* return the torque tile encoded in an efficient javascript
|
||||
* structure:
|
||||
* {
|
||||
* x:Uint8Array x coordinates in tile reference system, normally from 0-255
|
||||
* y:Uint8Array y coordinates in tile reference system
|
||||
* Index: Array index to the properties
|
||||
* }
|
||||
*/
|
||||
proccessTile: function(rows, coord, zoom) {
|
||||
var r;
|
||||
var x = new Uint8Array(rows.length);
|
||||
var y = new Uint8Array(rows.length);
|
||||
|
||||
var prof_mem = Profiler.metric('ProviderJSON:mem');
|
||||
var prof_point_count = Profiler.metric('ProviderJSON:point_count');
|
||||
var prof_process_time = Profiler.metric('ProviderJSON:process_time').start()
|
||||
|
||||
// count number of dates
|
||||
var dates = 0;
|
||||
var maxDateSlots = -1;
|
||||
for (r = 0; r < rows.length; ++r) {
|
||||
var row = rows[r];
|
||||
dates += row.dates__uint16.length;
|
||||
for(var d = 0; d < row.dates__uint16.length; ++d) {
|
||||
maxDateSlots = Math.max(maxDateSlots, row.dates__uint16[d]);
|
||||
}
|
||||
}
|
||||
|
||||
if(this.options.cumulative) {
|
||||
dates = (1 + maxDateSlots) * rows.length;
|
||||
}
|
||||
|
||||
var type = this.options.cumulative ? Uint32Array: Uint8Array;
|
||||
|
||||
// reserve memory for all the dates
|
||||
var timeIndex = new Int32Array(maxDateSlots + 1); //index-size
|
||||
var timeCount = new Int32Array(maxDateSlots + 1);
|
||||
var renderData = new (this.options.valueDataType || type)(dates);
|
||||
var renderDataPos = new Uint32Array(dates);
|
||||
|
||||
prof_mem.inc(
|
||||
4 * maxDateSlots + // timeIndex
|
||||
4 * maxDateSlots + // timeCount
|
||||
dates + //renderData
|
||||
dates * 4
|
||||
); //renderDataPos
|
||||
|
||||
prof_point_count.inc(rows.length);
|
||||
|
||||
var rowsPerSlot = {};
|
||||
|
||||
// precache pixel positions
|
||||
for (var r = 0; r < rows.length; ++r) {
|
||||
var row = rows[r];
|
||||
x[r] = row.x__uint8 * this.options.resolution;
|
||||
// fix value when it's in the tile EDGE
|
||||
// TODO: this should be fixed in SQL query
|
||||
if (row.y__uint8 === -1) {
|
||||
y[r] = 0;
|
||||
} else {
|
||||
y[r] = row.y__uint8 * this.options.resolution;
|
||||
}
|
||||
|
||||
var dates = row.dates__uint16;
|
||||
var vals = row.vals__uint8;
|
||||
if (!this.options.cumulative) {
|
||||
for (var j = 0, len = dates.length; j < len; ++j) {
|
||||
var rr = rowsPerSlot[dates[j]] || (rowsPerSlot[dates[j]] = []);
|
||||
if(this.options.cumulative) {
|
||||
vals[j] += prev_val;
|
||||
}
|
||||
prev_val = vals[j];
|
||||
rr.push([r, vals[j]]);
|
||||
}
|
||||
} else {
|
||||
var valByDate = {}
|
||||
for (var j = 0, len = dates.length; j < len; ++j) {
|
||||
valByDate[dates[j]] = vals[j];
|
||||
}
|
||||
var accum = 0;
|
||||
|
||||
// extend the latest to the end
|
||||
for (var j = dates[0]; j <= maxDateSlots; ++j) {
|
||||
var rr = rowsPerSlot[j] || (rowsPerSlot[j] = []);
|
||||
var v = valByDate[j];
|
||||
if (v) {
|
||||
accum += v;
|
||||
}
|
||||
rr.push([r, accum]);
|
||||
}
|
||||
|
||||
/*var lastDateSlot = dates[dates.length - 1];
|
||||
for (var j = lastDateSlot + 1; j <= maxDateSlots; ++j) {
|
||||
var rr = rowsPerSlot[j] || (rowsPerSlot[j] = []);
|
||||
rr.push([r, prev_val]);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// for each timeslot search active buckets
|
||||
var renderDataIndex = 0;
|
||||
var timeSlotIndex = 0;
|
||||
var i = 0;
|
||||
for(var i = 0; i <= maxDateSlots; ++i) {
|
||||
var c = 0;
|
||||
var slotRows = rowsPerSlot[i]
|
||||
if(slotRows) {
|
||||
for (var r = 0; r < slotRows.length; ++r) {
|
||||
var rr = slotRows[r];
|
||||
++c;
|
||||
renderDataPos[renderDataIndex] = rr[0]
|
||||
renderData[renderDataIndex] = rr[1];
|
||||
++renderDataIndex;
|
||||
}
|
||||
}
|
||||
timeIndex[i] = timeSlotIndex;
|
||||
timeCount[i] = c;
|
||||
timeSlotIndex += c;
|
||||
}
|
||||
|
||||
prof_process_time.end();
|
||||
|
||||
return {
|
||||
x: x,
|
||||
y: y,
|
||||
z: zoom,
|
||||
coord: {
|
||||
x: coord.x,
|
||||
y: coord.y,
|
||||
z: zoom
|
||||
},
|
||||
timeCount: timeCount,
|
||||
timeIndex: timeIndex,
|
||||
renderDataPos: renderDataPos,
|
||||
renderData: renderData,
|
||||
maxDate: maxDateSlots
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
_extraParams: function() {
|
||||
if (this.options.extra_params) {
|
||||
var p = [];
|
||||
for(var k in this.options.extra_params) {
|
||||
var v = this.options.extra_params[k];
|
||||
if (v) {
|
||||
p.push(k + "=" + encodeURIComponent(v));
|
||||
}
|
||||
}
|
||||
return p.join('&');
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
isHttps: function() {
|
||||
return this.options.sql_api_protocol && this.options.sql_api_protocol === 'https';
|
||||
},
|
||||
|
||||
// execute actual query
|
||||
getTileData: function(coord, zoom, callback) {
|
||||
var template = this.tileUrl(coord, zoom);
|
||||
var self = this;
|
||||
var fetchTime = Profiler.metric('jsonarray:fetch time');
|
||||
fetchTime.start();
|
||||
torque.net.get(template, function (data) {
|
||||
fetchTime.end();
|
||||
if (data) {
|
||||
data = self.proccessTile(JSON.parse(data.responseText).tile, coord, zoom);
|
||||
}
|
||||
callback(data);
|
||||
});
|
||||
},
|
||||
|
||||
url: function() {
|
||||
return this.options.url;
|
||||
},
|
||||
|
||||
tileUrl: function(coord, zoom) {
|
||||
var template = this.url();
|
||||
var s = (this.options.subdomains || 'abcd')[(coord.x + coord.y + zoom) % 4];
|
||||
return template
|
||||
.replace('{x}', coord.x)
|
||||
.replace('{y}', coord.y)
|
||||
.replace('{z}', zoom)
|
||||
.replace('{s}', s);
|
||||
},
|
||||
|
||||
getKeySpan: function() {
|
||||
return {
|
||||
start: this.options.start * 1000,
|
||||
end: this.options.end * 1000,
|
||||
step: this.options.step,
|
||||
steps: this.options.steps,
|
||||
};
|
||||
},
|
||||
|
||||
setColumn: function(column, isTime) {
|
||||
this.options.column = column;
|
||||
this.reload();
|
||||
},
|
||||
|
||||
setResolution: function(res) {
|
||||
this.options.resolution = res;
|
||||
},
|
||||
|
||||
// return true if tiles has been changed
|
||||
setOptions: function(opt) {
|
||||
var refresh = false;
|
||||
|
||||
if(opt.resolution !== undefined && opt.resolution !== this.options.resolution) {
|
||||
this.options.resolution = opt.resolution;
|
||||
refresh = true;
|
||||
}
|
||||
|
||||
if(opt.steps !== undefined && opt.steps !== this.options.steps) {
|
||||
this.setSteps(opt.steps, { silent: true });
|
||||
refresh = true;
|
||||
}
|
||||
|
||||
if(opt.column !== undefined && opt.column !== this.options.column) {
|
||||
this.options.column = opt.column;
|
||||
refresh = true;
|
||||
}
|
||||
|
||||
if(opt.countby !== undefined && opt.countby !== this.options.countby) {
|
||||
this.options.countby = opt.countby;
|
||||
refresh = true;
|
||||
}
|
||||
|
||||
return refresh;
|
||||
|
||||
},
|
||||
|
||||
getSteps: function() {
|
||||
return Math.min(this.options.steps, this.options.data_steps);
|
||||
},
|
||||
|
||||
setSteps: function(steps, opt) {
|
||||
},
|
||||
|
||||
getBounds: function() {
|
||||
}
|
||||
};
|
||||
|
||||
torque.providers.json = json;
|
||||
|
||||
|
||||
})(typeof exports === "undefined" ? this : exports);
|
Loading…
Reference in New Issue
Block a user