commit
7ea3709bee
1
NEWS
1
NEWS
@ -5,6 +5,7 @@
|
||||
- Add no_cdn option to windshaft provider
|
||||
- Add getActivePointsBBox method
|
||||
- Added renderer cache when the map is not animated
|
||||
- Added interaction method
|
||||
|
||||
2.4.01
|
||||
- fixed rectangle anchor and size #42
|
||||
|
123
doc/API.md
123
doc/API.md
@ -1,13 +1,6 @@
|
||||
|
||||
# Torque API
|
||||
|
||||
Torque provides two kinds of visualizations.
|
||||
|
||||
- static: provides a way to create heatmap like visualizations (note for Andrew: fon). see ``TorqueLayer``
|
||||
- dynamic: animate points over a map (note for Andrew: Navy) see ``TiledTorqueLayer``
|
||||
|
||||
|
||||
depending on the map provider you are using you need to use different layer type. Currently we provide layers for Google Maps and Leaflet.
|
||||
|
||||
## L.TorqueLayer(options)
|
||||
|
||||
@ -20,12 +13,7 @@ One of two core classes for the Torque library - it is used to create an animate
|
||||
var torqueLayer = new L.TorqueLayer({
|
||||
user : 'viz2',
|
||||
table : 'ow',
|
||||
column : 'date',
|
||||
countby : 'count(cartodb_id)',
|
||||
resolution : 1,
|
||||
steps : 750,
|
||||
pixel_size : 3,
|
||||
blendmode : 'lighter'
|
||||
cartocss: CARTOCSS
|
||||
});
|
||||
```
|
||||
|
||||
@ -34,37 +22,29 @@ One of two core classes for the Torque library - it is used to create an animate
|
||||
##### Provider options
|
||||
| Option | type | Default | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| provider | string | ```sql_api``` | Where is the data coming from? Alternative is 'url_template'|
|
||||
| provider | string | ```sql_api``` | Where is the data coming from |
|
||||
|
||||
##### CartoDB data options
|
||||
##### CartoDB data options (SQL API provider)
|
||||
| Option | type | Default | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| user | string | ```null``` | CartoDB account name. Found as, accountname.cartodb.com|
|
||||
| table | string | ```null``` | CartoDB table name where data is found |
|
||||
| column | string | ```null``` | CartoDB table's column name where date information is found (for dynamic type torque layer only)|
|
||||
| countby | string | ```null``` | The aggregation method to use for each pixel displayed where multiple data are found. Any valid PostgreSQL aggregate function |
|
||||
| table | string | ```null``` | CartoDB table name where data is found |
|
||||
| sql | string | ```null``` | SQL query to be performed to fetch the data. You must
|
||||
use this param or table, not at the same time |
|
||||
|
||||
|
||||
##### Display options
|
||||
| Option | type | Default | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| resolution| numeric | ```2``` | The x and y dimensions of each pixel as returned by the data|
|
||||
| blendmode | boolean | ```source-over``` | The HTML5 Canvas composite operation for when multiple pixels overlap on the canvas |
|
||||
|
||||
##### Time options
|
||||
| Option | type | Default | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| steps | integer | ```100``` | The maximun number of steps to divide the data into for animated renderings |
|
||||
| animationDuration | integer | ```null``` | time in seconds the animation last |
|
||||
|
||||
### Time methods
|
||||
|
||||
| Method | options | returns | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| ```setStep(step)``` | ```time numeric``` | ```this``` | sets the animation to the step indicated by ```step```, must be between 0 and ```steps```|
|
||||
| ```play```| | ```this```| starts the animation
|
||||
| ```stop```| | ```this```| stops the animation and set time to step 0
|
||||
| ```pause```| | ```this```| stops the animation but keep the current time (play enables the animation again)
|
||||
| ```play()```| | ```this```| starts the animation
|
||||
| ```stop()```| | ```this```| stops the animation and set time to step 0
|
||||
| ```pause()```| | ```this```| stops the animation but keep the current time (play enables the animation again)
|
||||
| ```toggle()```| | ```this```| toggles (pause/play) the animation
|
||||
| ```getStep()``` | | current animation step (integer) | gets the current animation step
|
||||
| ```getTime()``` | | current animation time (Date) | gets the real animation time
|
||||
|
||||
|
||||
|
||||
### Style methods
|
||||
@ -97,63 +77,16 @@ This should be ```string``` encoded in Javascript
|
||||
}
|
||||
```
|
||||
|
||||
## L.TiledTorqueLayer(options)
|
||||
|
||||
One of two core classes for the Torque library - it is used to create a static torque layer with client side filtering.
|
||||
|
||||
##### Provider options
|
||||
| Option | type | Default | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| provider | string | ```sql_api``` | Where is the data coming from? Alternative is 'url_template'|
|
||||
| url | string | ```null``` | Tile template URL for fetching data e.g 'http://host.com/{z}/{x}/{y}.json'|
|
||||
|
||||
##### CartoDB data options (Note to Santana: are these really here?)
|
||||
| Option | type | Default | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| user | string | ```null``` | CartoDB account name. Found as, accountname.cartodb.com|
|
||||
| table | string | ```null``` | CartoDB table name where data is found |
|
||||
| column | string | ```null``` | CartoDB table's column name where date information is found (for dynamic type torque layer only)|
|
||||
| countby | string | ```null``` | The aggregation method to use for each pixel displayed where multiple data are found. Any valid PostgreSQL aggregate function |
|
||||
|
||||
|
||||
##### Display options (Note to Santana: is blendmode here? or above even?)
|
||||
| Option | type | Default | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| resolution| numeric | ```2``` | The x and y dimensions of each pixel as returned by the data|
|
||||
| blendmode | boolean | ```source-over``` | The HTML5 Canvas composite operation for when multiple pixels overlap on the canvas |
|
||||
|
||||
### Filtering options
|
||||
|
||||
### Interaction methods (only available for Leaflet)
|
||||
| Method | options | returns | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| ```setKey(keys)``` | ```keys numeric/array``` | ```this``` | which data categories to display on the map |
|
||||
| ```setSQL(sql)``` | ```sql string ``` | ```this``` | by default sql torque layer uses is
|
||||
"select * from table", this method changes the sql query torque uses to fetch the data |
|
||||
| ```getValueForPos(x, y[, step])```| | an object like { bbox:[], value: VALUE } if there is value
|
||||
for the pos, null otherwise | allows to get the value for the coordinate (in map reference system)
|
||||
for a concrete step. If step is not specified the animation one is used. This method is expensive
|
||||
in terms of CPU so be careful. It returns the value from the raster data not the rendered data |
|
||||
| ```getActivePointsBBox(step)```| | list of bbox | returns the list of bounding boxes active for
|
||||
``step``
|
||||
|
||||
### Style options
|
||||
|
||||
| Method | options | returns | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| ```setCartoCSS(cartocss)``` | ```cartocss string``` | ```this``` | style the map rendering using client-side cartocss |
|
||||
|
||||
``value`` and ``zoom`` variables can be used. only ``polygon-fill`` and ``polygon-opacity`` properties are supported currently. To see the full list of supported parameters, read the [Torque CartoCSS documentation here](CartoCSS.md).
|
||||
|
||||
TorqueLayer currently expects ```polygon``` styling
|
||||
|
||||
##### CartoCSS Example
|
||||
|
||||
This should be ```string``` encoded in Javascript
|
||||
|
||||
```css
|
||||
#layer {
|
||||
polygon-fill: #FFFF00;
|
||||
[value >= 10] { polygon-fill: #FFCC00; }
|
||||
[value >= 100] { polygon-fill: #FF9900; }
|
||||
[value >= 1000] { polygon-fill: #FF6600; }
|
||||
[value >= 10000] { polygon-fill: #FF3300; }
|
||||
[value > 100000] { polygon-fill: #C00; }
|
||||
}
|
||||
```
|
||||
|
||||
# Google Maps Layers
|
||||
|
||||
@ -171,19 +104,3 @@ is not a layer is a overlay so in order to add it to the map use ``layer.setMap`
|
||||
see ``L.TorqueLayer`` for the rest of the options.
|
||||
|
||||
|
||||
## GMapsTiledTorqueLayer(options)
|
||||
creates a static _overlay_ to use it with google maps.
|
||||
|
||||
```js
|
||||
var torqueLayer = new torque.GMapsTiledTorqueLayer({
|
||||
provider: 'url_template',
|
||||
url: GBIF_URL,
|
||||
resolution: 4,
|
||||
});
|
||||
|
||||
torqueLayer.setMap(map);
|
||||
|
||||
torqueLayer.setKey([10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]);
|
||||
```
|
||||
|
||||
see ``L.TiledTorqueLayer`` for options reference
|
||||
|
108
examples/leaflet_interaction.html
Normal file
108
examples/leaflet_interaction.html
Normal file
@ -0,0 +1,108 @@
|
||||
|
||||
<html>
|
||||
<link rel="stylesheet" href="../vendor/leaflet.css" />
|
||||
<style>
|
||||
#map, html, body {
|
||||
width: 100%; height: 100%; padding: 0; margin: 0;
|
||||
}
|
||||
#title {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 50px;
|
||||
color: white;
|
||||
font-size: 27px;
|
||||
font-family: Helvetica, sans-serif;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
<div id="title">Average temperature collected by Britain's Royal Navy (1913-1925)</div>
|
||||
|
||||
<script src="../vendor/leaflet.js"></script>
|
||||
<script src="../vendor/underscore.js"></script>
|
||||
<script src="../vendor/carto.js"></script>
|
||||
<script src="../dist/torque.uncompressed.js"></script>
|
||||
|
||||
|
||||
<script>
|
||||
// define the torque layer style using cartocss
|
||||
// this creates a kind of density map
|
||||
//color scale from http://colorbrewer2.org/
|
||||
var CARTOCSS = [
|
||||
'Map {',
|
||||
'-torque-time-attribute: "date";',
|
||||
'-torque-aggregation-function: "avg(temp::float)";',
|
||||
'-torque-frame-count: 1;',
|
||||
'-torque-animation-duration: 15;',
|
||||
'-torque-resolution: 16',
|
||||
'}',
|
||||
'#layer {',
|
||||
' marker-width: 8;',
|
||||
' marker-fill-opacity: 1.0;',
|
||||
' marker-fill: #fff5eb; ',
|
||||
' marker-type: rectangle;',
|
||||
' [value > 1] { marker-fill: #fee6ce; }',
|
||||
' [value > 2] { marker-fill: #fdd0a2; }',
|
||||
' [value > 4] { marker-fill: #fdae6b; }',
|
||||
' [value > 10] { marker-fill: #fd8d3c; }',
|
||||
' [value > 15] { marker-fill: #f16913; }',
|
||||
' [value > 20] { marker-fill: #d94801; }',
|
||||
' [value > 25] { marker-fill: #8c2d04; }',
|
||||
'}'
|
||||
].join('\n');
|
||||
|
||||
|
||||
var map = new L.Map('map', {
|
||||
zoomControl: true,
|
||||
center: [40, 0],
|
||||
zoom: 3
|
||||
});
|
||||
|
||||
L.tileLayer('http://{s}.api.cartocdn.com/base-dark/{z}/{x}/{y}.png', {
|
||||
attribution: 'CartoDB'
|
||||
}).addTo(map);
|
||||
|
||||
var torqueLayer = new L.TorqueLayer({
|
||||
user : 'viz2',
|
||||
table : 'ow',
|
||||
cartocss: CARTOCSS
|
||||
});
|
||||
torqueLayer.addTo(map);
|
||||
|
||||
map.on('click', function(e) {
|
||||
var p = e.containerPoint
|
||||
var value = torqueLayer.getValueForPos(p.x, p.y);
|
||||
if (value !== null) {
|
||||
map.openPopup('average temperature: ' + value.value + "C", e.latlng);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// show small rectable and change cursor on hover
|
||||
var hover = null;
|
||||
map.on('mousemove', function(e) {
|
||||
var p = e.containerPoint
|
||||
var value = torqueLayer.getValueForPos(p.x, p.y);
|
||||
|
||||
// remove previous hover box
|
||||
if (hover) {
|
||||
map.removeLayer(hover);
|
||||
hover = null;
|
||||
}
|
||||
|
||||
if (value !== null) {
|
||||
hover = L.rectangle(value.bbox, {
|
||||
color: '#000',
|
||||
weight: 1
|
||||
}).addTo(map);
|
||||
map._container.style.cursor = 'pointer';
|
||||
} else {
|
||||
map._container.style.cursor = 'auto';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -330,6 +330,27 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
positions = positions.concat(this.renderer.getActivePointsBBox(tile, step));
|
||||
}
|
||||
return positions;
|
||||
},
|
||||
|
||||
/**
|
||||
* return the value for position relative to map coordinates. null for no value
|
||||
*/
|
||||
getValueForPos: function(x, y, step) {
|
||||
step = step === undefined ? this.key: step;
|
||||
var t, tile, pos, value = null, xx, yy;
|
||||
for(t in this._tiles) {
|
||||
tile = this._tiles[t];
|
||||
pos = this.getTilePos(tile.coord);
|
||||
xx = x - pos.x;
|
||||
yy = y - pos.y;
|
||||
if (xx >= 0 && yy >= 0 && xx < this.renderer.TILE_SIZE && yy <= this.renderer.TILE_SIZE) {
|
||||
value = this.renderer.getValueFor(tile, step, xx, yy);
|
||||
}
|
||||
if (value !== null) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -59,9 +59,10 @@ MercatorProjection.prototype._tilePixelPos = function(tileX, tileY) {
|
||||
};
|
||||
};
|
||||
|
||||
MercatorProjection.prototype.tilePixelBBox = function(x, y, zoom, px, py) {
|
||||
MercatorProjection.prototype.tilePixelBBox = function(x, y, zoom, px, py, res) {
|
||||
res = res || 1.0;
|
||||
var numTiles = 1 <<zoom;
|
||||
var inc = 1.0/numTiles;
|
||||
var inc = res/numTiles;
|
||||
px = (x*this._tileSize + px)/numTiles;
|
||||
py = (y*this._tileSize + py)/numTiles;
|
||||
return [
|
||||
|
@ -187,6 +187,41 @@
|
||||
}
|
||||
}
|
||||
return positions;
|
||||
},
|
||||
|
||||
// return the value for x, y (tile coordinates)
|
||||
// null for no value
|
||||
getValueFor: function(tile, step, px, py) {
|
||||
var mercator = new torque.Mercator();
|
||||
var res = this.options.resolution;
|
||||
var res2 = res >> 1;
|
||||
|
||||
var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1);
|
||||
//this.renderer.renderTile(tile, this.key, pos.x, pos.y);
|
||||
var activePixels = tile.timeCount[step];
|
||||
var pixelIndex = tile.timeIndex[step];
|
||||
for(var p = 0; p < activePixels; ++p) {
|
||||
var posIdx = tile.renderDataPos[pixelIndex + p];
|
||||
var c = tile.renderData[pixelIndex + p];
|
||||
if (c) {
|
||||
var x = tile.x[posIdx];
|
||||
var y = tileMax - tile.y[posIdx];
|
||||
var dx = px + res2 - x;
|
||||
var dy = py + res2 - y;
|
||||
if (dx >= 0 && dx < res && dy >= 0 && dy < res) {
|
||||
return {
|
||||
value: c,
|
||||
bbox: mercator.tilePixelBBox(
|
||||
tile.coord.x,
|
||||
tile.coord.y,
|
||||
tile.coord.z,
|
||||
x - res2, y - res2, res
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -47,3 +47,31 @@ test('render conditional point layers', function() {
|
||||
st = layer.getStyle('canvas-2d', {}, { zoom: 18, 'frame-offset': 0 });
|
||||
equal(st['point-radius'], 20);
|
||||
});
|
||||
|
||||
test('get value for position', function() {
|
||||
var mercator = new torque.Mercator();
|
||||
tile = {
|
||||
timeCount: [1],
|
||||
timeIndex: [0],
|
||||
renderDataPos: [0],
|
||||
renderData: [5],
|
||||
x: [100],
|
||||
y: [3],
|
||||
coord: { x: 0, y: 0, z: 0 }
|
||||
};
|
||||
renderer.options = {
|
||||
resolution: 1
|
||||
};
|
||||
var v = renderer.getValueFor(tile, 0, 100, 255 - 3);
|
||||
var bbox = mercator.tilePixelBBox(0, 0, 0, 100, 255 - 3, 1);
|
||||
equal(v.bbox[0].lat, bbox[0].lat);
|
||||
equal(v.bbox[1].lat, bbox[1].lat);
|
||||
equal(v.bbox[0].lon, bbox[0].lon);
|
||||
equal(v.bbox[1].lon, bbox[1].lon);
|
||||
equal(v.value, 5);
|
||||
|
||||
v = renderer.getValueFor(tile, 0, 100, 255 - 4);
|
||||
equal(v, null);
|
||||
v = renderer.getValueFor(tile, 0, 99, 255 - 3);
|
||||
equal(v, null);
|
||||
});
|
||||
|
@ -16,6 +16,7 @@
|
||||
<script src="../lib/torque/core.js"></script>
|
||||
<script src="../lib/torque/profiler.js"></script>
|
||||
<script src="../lib/torque/request.js"></script>
|
||||
<script src="../lib/torque/mercator.js"></script>
|
||||
<script src="../lib/torque/leaflet/leaflet_tileloader_mixin.js"></script>
|
||||
<script src="../lib/torque/leaflet/canvas_layer.js"></script>
|
||||
<script src="../lib/torque/renderer/point.js"></script>
|
||||
|
Loading…
Reference in New Issue
Block a user