Compare commits

..

656 Commits
heat ... master

Author SHA1 Message Date
Simon Martín
11b73bbc9a Stubs next version 2019-06-25 10:26:27 +02:00
Simon Martín
f6217eaed0 updating NEWS 2019-06-24 17:46:00 +02:00
Simon Martín
63e70d1446
Merge pull request #307 from CartoDB/306-fix-cannot-read-undefined-layer
306 fix cannot read undefined layer
2019-06-24 17:44:32 +02:00
Simon Martín
62bc50b129 version 3.1.1 2019-06-21 10:35:08 +02:00
Rafa de la Torre
c62c4f548e Use turbocarto only if there's a layer 2019-06-14 15:12:21 +02:00
Rafa de la Torre
3a782117f5 Strip comments out of cartocss 2019-06-14 15:09:39 +02:00
Rafa de la Torre
58664a2f47 Add a test for faulty scenario 2019-06-14 15:01:24 +02:00
Daniel García Aubert
4d2540ef98 Stubs next version 2019-04-02 17:47:14 +02:00
Daniel García Aubert
eb06dd1e63 Release 3.1.0 2019-04-02 10:26:23 +02:00
Daniel G. Aubert
a44bf1866c
Merge pull request #305 from CartoDB/upgrade-canvas
Upgrade canvas version to 2.4.1
2019-04-02 10:25:19 +02:00
Daniel García Aubert
adbeb066cc Update next release version and NEWS 2019-04-02 10:07:30 +02:00
Daniel García Aubert
8da4889d17 Adapt test to the new version of canvas 2019-03-29 16:20:13 +01:00
Daniel García Aubert
dae2531d5c Update contributors 2019-03-29 16:11:47 +01:00
Daniel García Aubert
c2346d5979 Upgrade canvas version to 2.4.1 2019-03-29 16:09:52 +01:00
Daniel García Aubert
db9290d990 Stubs next version 2019-03-29 11:34:43 +01:00
Daniel García Aubert
5529351215 Release 3.0.0 2019-03-29 11:06:58 +01:00
Daniel G. Aubert
878d5c418b
Merge pull request #304 from CartoDB/avoid-uncaught-exception
Avoid uncaught exception 'Error: Image given has not completed loading'
2019-03-29 11:05:33 +01:00
Daniel García Aubert
3f3bd97dd6 Update NEWS 2019-03-28 15:40:17 +01:00
Daniel García Aubert
47a2c4fda8 Drop support for Node.js 6 and 8 2019-03-28 15:39:54 +01:00
Daniel García Aubert
0edffef74b Avoid uncaught exception 'Error: Image given has not completed loading' while drawing with canvas 2019-03-28 15:31:48 +01:00
cillas
2f97d7fda0
Merge pull request #291 from CartoDB/developer-center
New docs folder for developer center
2019-03-11 10:56:44 +01:00
Víctor Velarde
9f66475278 Add new 'Static' category to examples and remove description 2019-03-08 11:36:18 +01:00
Víctor Velarde
9b680db46c Rename OpenLayers example 2019-03-07 17:42:34 +01:00
csubira
890f4a5da1 Relocate and refactor examples folder in doc 2019-03-07 12:56:04 +01:00
csubira
71b5c07420 Replace older links to deprecated docs site 2019-03-06 15:14:39 +01:00
csubira
05fb3cfc18 Remove older doc folder 2019-03-01 16:29:47 +01:00
Daniel García Aubert
23101417f2 Release 2.17.1 2019-01-23 17:24:57 +01:00
Daniel G. Aubert
ef9de16c2d
Merge pull request #300 from CartoDB/audit-deps
Audit dependencies
2019-01-23 17:15:47 +01:00
Daniel García Aubert
bb0f5118ed Update NEWS 2019-01-22 19:19:36 +01:00
Daniel García Aubert
be0d9d5063 Build dist files 2019-01-21 18:00:17 +01:00
Daniel García Aubert
26252f3841 Do not forget callbacks 2019-01-21 17:15:14 +01:00
Daniel García Aubert
ca8634530e Update devel deps 2019-01-21 16:49:05 +01:00
Daniel García Aubert
a06871eb42 Update turbo-carto & request 2019-01-21 12:45:01 +01:00
Ivan Malagon
ebd978fe7d Hide some examples 2018-12-03 16:24:58 +01:00
Ivan Malagon
7200f9b7fe Add port to examples 2018-12-03 16:14:42 +01:00
Ivan Malagon
69857f7335
Merge pull request #299 from CartoDB/update-examples
Update Torque examples
2018-12-03 15:18:21 +01:00
Ivan Malagon
6489c8a743 Update examples 2018-12-03 14:53:13 +01:00
Daniel García Aubert
96fa54bb98 Stubs next version 2018-11-21 10:15:20 +01:00
Daniel García Aubert
80a7757fdf Release 2.17.0 2018-11-21 10:13:40 +01:00
Daniel G. Aubert
8664c32b74
Merge pull request #296 from CartoDB/nodejs-10
Support Nodejs 10 LTS
2018-11-21 10:12:52 +01:00
Daniel García Aubert
54f5389805 Prepare next release 2018-11-21 10:03:38 +01:00
Iñigo Medina (aka MacGyver)
8142d2622e
update HTTP to HTTPS 2018-10-30 15:23:19 +01:00
Daniel García Aubert
6a60af93b7 Add support for Node 8 & 10 2018-10-29 17:57:32 +01:00
Daniel García Aubert
286473fadb Downgrade canvas to version 1.6.9 2018-10-29 17:48:24 +01:00
Daniel García Aubert
69ad01bf9e Support package-lock.json file 2018-10-29 17:28:45 +01:00
Daniel García Aubert
7cf5d6a590 Require @carto/mapnik 2018-10-29 17:25:24 +01:00
Daniel García Aubert
3f71d1e40c Update canvas 2018-10-29 17:23:59 +01:00
Daniel García Aubert
397dec86b1 Use our current fork of mapnik while testing 2018-10-29 17:23:21 +01:00
cillas
40142ca244
Correct typos in examples.json 2018-05-22 11:19:35 +02:00
IagoLast
ce414701ab 2.16.5 2018-05-10 16:04:14 +02:00
IagoLast
a0e108ac23 2.16.4 2018-05-10 16:04:01 +02:00
IagoLast
4cfeff4054 Add release scripts 2018-05-10 16:03:56 +02:00
Iñigo Medina (aka MacGyver)
03b0f4059a
Update 01-getting-started.md 2018-05-07 12:39:44 +02:00
IagoLast
f4720e0736
Merge pull request #294 from CartoDB/1498-fix-time-series-gmaps
Fix time series google map
2018-05-04 11:06:59 +02:00
IagoLast
e784dcb048 Fix time series google map
Check if layer exists to prevent an error.
More info [here](https://github.com/CartoDB/support/issues/1498#issuecomment-386035383)
2018-05-03 13:12:36 +02:00
Iñigo Medina
783303bc31
Update 05-how-spatial-aggregation-works.md 2018-04-23 12:38:07 +02:00
Iñigo Medina
7dc5703cf4
Update static_heat_map_simple.html 2018-04-18 01:40:13 +02:00
Iñigo Medina
efca29f374
Update static_heat_map.html 2018-04-18 01:39:25 +02:00
Iñigo Medina
8a3bccd0c9
Update examples.json 2018-04-18 01:34:24 +02:00
Iñigo Medina
a8da0581d1
Update static_bubble_map.html 2018-04-18 01:33:38 +02:00
Iñigo Medina
be43a32eeb
Update static_bubble_map.html 2018-04-17 20:57:42 +02:00
Iñigo Medina
7cbe86259e
Update examples.json 2018-04-17 20:37:36 +02:00
Iñigo Medina
02575e0991
Update static_heat_map.html 2018-04-17 20:25:25 +02:00
Iñigo Medina
7178906519
Update 02-contribute.md 2018-04-17 14:39:09 +02:00
Iñigo Medina
5bf0330d0e
Update examples.json 2018-04-13 14:18:51 +02:00
Iñigo Medina
5a507f2723
Update examples.json 2018-04-13 14:16:27 +02:00
Iñigo Medina
35fa94ba7b
Update examples.json 2018-04-13 14:13:54 +02:00
Iñigo Medina
3e293ba982
Create navy_gmaps.html 2018-04-13 14:08:01 +02:00
Iñigo Medina
ea3a49586c
Create light_bright.html 2018-04-13 14:07:42 +02:00
Iñigo Medina
7a64469f57
Create leafleft_interaction.html 2018-04-13 14:07:25 +02:00
Iñigo Medina
7b8fd95f69
Create car.html 2018-04-13 14:06:56 +02:00
Iñigo Medina
e9e30b7541
Update examples.json 2018-04-13 14:06:27 +02:00
Iñigo Medina
9012fd7d68
Update 12-Google-maps-layers.md 2018-04-13 10:58:25 +02:00
Iñigo Medina
a01dd84505
Update 11-events.md 2018-04-13 10:58:10 +02:00
Iñigo Medina
eb09121165
Update 10-data-methods.md 2018-04-13 10:57:57 +02:00
Iñigo Medina
a0e02c1c03
Update 09-style-methods.md 2018-04-13 10:57:44 +02:00
Iñigo Medina
fa25acf13e
Update 08-layer-control-methods.md 2018-04-13 10:57:31 +02:00
Iñigo Medina
ebadade6c1
Update 07-time-methods.md 2018-04-13 10:57:20 +02:00
Iñigo Medina
8573862459
Update 06-providing-a-TileJSON-file.md 2018-04-13 10:56:58 +02:00
Iñigo Medina
caee1c28c1
Update 05-using-a-custom-SQL-query.md 2018-04-13 10:56:46 +02:00
Iñigo Medina
64fdddd1a5
Update 04-using-a-CARTO-table-directly.md 2018-04-13 10:56:36 +02:00
Iñigo Medina
9d76b2d4fd
Update 03-L.TorqueLayer.md 2018-04-13 10:56:24 +02:00
Iñigo Medina
72faba5cb7
Create image 2018-04-13 10:54:58 +02:00
Iñigo Medina
d1922506ac
Rename 10-Google-maps-layers.md to 12-Google-maps-layers.md 2018-04-13 10:54:10 +02:00
Iñigo Medina
6d8f6c746a
Rename 09-events.md to 11-events.md 2018-04-13 10:53:57 +02:00
Iñigo Medina
d70af4d2e4
Rename 08-data-methods.md to 10-data-methods.md 2018-04-13 10:53:44 +02:00
Iñigo Medina
d137c14372
Rename 07-style-methods.md to 09-style-methods.md 2018-04-13 10:53:32 +02:00
Iñigo Medina
b631de3c7d
Rename 06-layer-control-methods.md to 08-layer-control-methods.md 2018-04-13 10:53:19 +02:00
Iñigo Medina
bffc34f87a
Rename 05-time-methods.md to 07-time-methods.md 2018-04-13 10:53:06 +02:00
Iñigo Medina
fb5f13ef2f
Rename 04-providing-a-TileJSON-file.md to 06-providing-a-TileJSON-file.md 2018-04-13 10:52:53 +02:00
Iñigo Medina
965cbffb70
Rename 03-using-a-custom-SQL-query.md to 05-using-a-custom-SQL-query.md 2018-04-13 10:52:41 +02:00
Iñigo Medina
ed22c66062
Rename 02-using-a-CARTO-table-directly.md to 04-using-a-CARTO-table-directly.md 2018-04-13 10:52:26 +02:00
Iñigo Medina
208c1de62c
Rename 01-L.TorqueLayer.md to 03-L.TorqueLayer.md 2018-04-13 10:52:06 +02:00
Iñigo Medina
60b8a065a9
Create 02-versioning.md 2018-04-13 10:51:44 +02:00
Iñigo Medina
f007de5883
Create 01-introduction.md 2018-04-13 10:50:38 +02:00
Iñigo Medina
b2c92475c4
Update car.html 2018-04-12 21:10:50 +02:00
Iñigo Medina
fd0ed66c9f
Rename 02-CartoCSS.md to 02-cartocss.md 2018-04-12 15:57:39 +02:00
Iñigo Medina
54b84f0312
Update 02-contribute.md 2018-04-12 15:43:30 +02:00
Iñigo Medina
61c508fd7b
Update 02-contribute.md 2018-04-12 15:42:54 +02:00
Iñigo Medina
a1b6483d64
Rename 03-how-spatial-aggregation-works.md to 05-how-spatial-aggregation-works.md 2018-04-12 14:06:24 +02:00
Iñigo Medina
6cb9051480
Create 04-torque-time-slider.md 2018-04-12 14:06:10 +02:00
Iñigo Medina
cde81fc1e7
Create 03-torque-interaction-methods.md 2018-04-12 14:05:43 +02:00
Iñigo Medina
5e83f5bd8b
Update 03-how-spatial-aggregation-works.md 2018-04-12 13:37:03 +02:00
Iñigo Medina
0f4f8a5319
Update 01-getting-started.md 2018-04-12 13:36:37 +02:00
Iñigo Medina
e6aaa10f67
Update 02-CartoCSS.md 2018-04-12 13:35:34 +02:00
Iñigo Medina
03248457e1
Update examples.json 2018-04-12 13:32:47 +02:00
Iñigo Medina
3fa971d044
Create 03-how-spatial-aggregation-works.md 2018-04-12 13:29:47 +02:00
Iñigo Medina
197c3d7824
Update 01-getting-started.md 2018-04-12 13:28:12 +02:00
Iñigo Medina
5666fbc187
Update examples.json 2018-04-12 13:27:12 +02:00
Iñigo Medina
07e9ee6d21
Update examples.json 2018-04-12 13:21:50 +02:00
Iñigo Medina
bdab824733
Create examples.json 2018-04-12 13:16:11 +02:00
Iñigo Medina
c2512a9b1e
Delete 02-torque-time-slider.md 2018-04-12 13:12:47 +02:00
Iñigo Medina
2f210b8783
Create torque-time-slider.md 2018-04-12 13:12:36 +02:00
Iñigo Medina
6314352a19
Delete 01-torque-interaction-methods.md 2018-04-12 13:12:14 +02:00
Iñigo Medina
95c7ba2a7e
Delete examples.json 2018-04-12 13:12:02 +02:00
Iñigo Medina
6aa54bfb0c
Create torque-interactions-methods.md 2018-04-12 13:11:50 +02:00
Iñigo Medina
b9765821be
Create examples.json 2018-04-12 13:11:00 +02:00
Iñigo Medina
7f0a61a8c4
Create examples.json 2018-04-12 13:10:24 +02:00
Iñigo Medina
2dee3662ae
Create 02-contribute.md 2018-04-12 13:07:51 +02:00
Iñigo Medina
bb6a4cbc06
Delete 01-torque-api.md 2018-04-12 13:05:29 +02:00
Iñigo Medina
14dbf9b7ec
Create 10-Google-maps-layers.md 2018-04-12 13:05:14 +02:00
Iñigo Medina
29bf52a70b
Create 09-events.md 2018-04-12 13:04:45 +02:00
Iñigo Medina
00a12cf968
Create 08-data-methods.md 2018-04-12 13:04:28 +02:00
Iñigo Medina
3c43265dcc
Create 07-style-methods.md 2018-04-12 13:04:12 +02:00
Iñigo Medina
9fa066c3bc
Create 06-layer-control-methods.md 2018-04-12 13:03:44 +02:00
Iñigo Medina
6f56aa05ad
Create 05-time-methods.md 2018-04-12 13:03:19 +02:00
Iñigo Medina
6f2b3b9cc2
Create 04-providing-a-TileJSON-file.md 2018-04-12 13:02:56 +02:00
Iñigo Medina
f7efb15a8f
Create 03-using-a-custom-SQL-query.md 2018-04-12 13:02:27 +02:00
Iñigo Medina
9b67ec1279
Create 02-using-a-CARTO-table-directly.md 2018-04-12 13:01:58 +02:00
Iñigo Medina
d80249f83d
Create 01-L.TorqueLayer.md 2018-04-12 13:01:17 +02:00
csubira
4a049eedce Fix title md and remove cartojs references in torque support section 2018-02-26 12:01:41 +01:00
Carlos Matallín
742c2d9808 prepare shield-placement-keyword CartoCSS property 2018-02-23 11:10:20 +01:00
Carlos Matallín
a8385cff5c
Merge pull request #293 from CartoDB/shield_placement_type
adds shield-placement-type to torque-reference
2018-02-23 11:06:00 +01:00
Carlos Matallín
e6451e0e7b prepare shield-placement-keyword CartoCSS property 2018-02-22 17:49:37 +01:00
csubira
792a66ccf9 Add new docs folder structure 2018-02-20 16:53:51 +01:00
Rubén Moya
5d9b02a6da
Merge pull request #288 from CartoDB/torque-platform-limits
Handle limit errors
2017-11-16 11:30:06 +01:00
rubenmoya
feb9fa3e01 Add showLimitErrors to gmaps/torque 2017-11-16 11:20:03 +01:00
rubenmoya
cf5a29c3a7 Build 2017-11-16 11:14:54 +01:00
Rubén Moya
27306dd917
Merge pull request #290 from CartoDB/289-torque-limits
Return custom torque tile when limits are reached
2017-11-16 11:13:40 +01:00
rubenmoya
5382d62141 Fix tests 2017-11-15 16:36:36 +01:00
rubenmoya
a67ad45b9c Update build 2017-11-15 16:25:56 +01:00
rubenmoya
664ab3f28b Update contributors 2017-11-15 16:24:25 +01:00
rubenmoya
23d2d2a60e Load error tile svg only if showLimitErrors is true 2017-11-15 16:24:13 +01:00
rubenmoya
b597fba4ae Render errorTile only when showLimitErrors is true 2017-11-15 15:14:42 +01:00
Carlos Matallín
73d1b1a9b5 build 2017-11-14 12:19:17 +01:00
Carlos Matallín
4c28eb7bdd error img url 2017-11-14 12:18:42 +01:00
Carlos Matallín
c3f25b08de build 2017-11-14 12:12:47 +01:00
Carlos Matallín
9c9c7253ba callback 2017-11-14 12:12:02 +01:00
Carlos Matallín
69cdd20c36 update contributors 2017-11-14 11:56:10 +01:00
Carlos Matallín
e0ddf8c9d1 build 2017-11-14 11:55:37 +01:00
Carlos Matallín
ffa1435d20 show limit error tiles 2017-11-14 11:54:36 +01:00
rubenmoya
34fee901ca Fix schrödingtest 2017-11-07 15:38:42 +01:00
rubenmoya
6311531550 Try .travis.yml 2017-11-07 15:23:15 +01:00
rubenmoya
27a752f49c Test travis.yml 2017-11-07 15:19:43 +01:00
rubenmoya
b7e00af3f7 Add custom ppa 2017-11-07 15:17:09 +01:00
rubenmoya
e745fac67b Edit .travis.yml 2017-11-07 15:12:21 +01:00
rubenmoya
f5bfaf7585 Try to fix travis 2017-11-07 14:52:10 +01:00
rubenmoya
ea6fc57384 Restore window.XMLHttpRequest when test finishes 2017-11-07 14:40:05 +01:00
rubenmoya
b75688dcd9 Update node version in travis.yml 2017-11-07 13:02:35 +01:00
rubenmoya
8d39f09a68 Mock ajax requests 2017-11-07 12:55:09 +01:00
rubenmoya
f669429861 Fix windshaft provider tests 2017-11-07 12:06:20 +01:00
rubenmoya
1aacc38d49 Update phantomjs 2017-11-07 12:06:01 +01:00
rubenmoya
daa9dd42b3 Add libpango to travis.yml 2017-11-07 11:51:34 +01:00
rubenmoya
8e714b6a1a Update mapnik to 3.5.14 2017-11-07 11:42:40 +01:00
rubenmoya
5d89990119 Handle limits error in GMaps 2017-11-07 11:35:17 +01:00
rubenmoya
e83bcaee6d Handle limit errors 2017-11-07 11:29:42 +01:00
Pablo Alonso Garcia
c998860ad3 README.md 2017-06-07 11:34:49 +02:00
Pablo Alonso Garcia
ae5afddba7 README.md 2017-06-07 11:33:39 +02:00
Francisco López
44c8e77213 Dist release 2017-04-18 15:32:28 +02:00
Francisco López
03bc7695a3 Merge pull request #286 from CartoDB/zoom-round-fix
Round zoom for flyto float values
2017-04-18 14:08:10 +02:00
Francisco López
4cfbe82ae1 Round zoom for flyto float values 2017-04-18 11:04:25 +02:00
Pablo Alonso
813b3b60dc Merge pull request #285 from CartoDB/unbind-move-event
Unbind map's 'move' event properly when layer is removed from the map
2017-03-27 13:05:03 +02:00
Pablo Alonso Garcia
deced717fd Dist files 2017-03-27 13:03:30 +02:00
Pablo Alonso Garcia
4e91bd5856 Stop the animator when L.Torque layer is removed from the map 2017-03-27 13:00:09 +02:00
Pablo Alonso Garcia
80172ac547 Merge remote-tracking branch 'origin/master' into unbind-move-event 2017-03-27 12:48:44 +02:00
Pablo Alonso Garcia
d50d74571b Fixed some examples (updated Leaflet to 1.0.3) 2017-03-27 12:48:03 +02:00
Pablo Alonso Garcia
88b2be378d Unbind 'move' event properly 2017-03-27 12:25:05 +02:00
Francisco López
f9e6b4f2f9 Merge pull request #284 from CartoDB/leaflet-migration
Migrate to leaflet 1.0.3
2017-03-27 10:29:49 +02:00
Francisco López
b94b4812c7 Restore onAdd method 2017-03-22 13:51:30 +01:00
Francisco López
490d91fe15 Fix translation 2017-03-21 17:53:56 +01:00
Francisco López
8b860d4205 Back to layer and add zIndex to the container 2017-03-21 17:33:21 +01:00
Francisco López
a82dbfb850 Fix smoke test errors 2017-03-21 17:00:40 +01:00
Francisco López
3752aacf33 Migrate to leaflet 1.0.3 2017-03-15 14:23:42 +01:00
Francisco López
771c92fb2f Stubs next version 2017-02-16 18:19:19 +01:00
Francisco López
2f6306dae3 Release 2.16.2 2017-02-16 18:18:10 +01:00
Francisco López
aac5d4a48b Stubs next version 2017-02-16 17:04:38 +01:00
Francisco López
b1fb8856da Release 2.16.1 2017-02-16 16:18:51 +01:00
Francisco López
a87657d5d1 Update news with last two PR 2017-02-16 16:18:03 +01:00
Francisco López
e20286ed84 Merge pull request #281 from CartoDB/clear-rect
Remove width trick to use clear rect, fix #280
2017-02-08 15:32:57 +01:00
Francisco López
ee95c112f9 Make a local variable of ctx 2017-02-08 15:03:45 +01:00
Francisco López
c847784a8f Merge pull request #279 from CartoDB/gmaps-support
Repair broken reference
2017-02-08 10:52:50 +01:00
Francisco López
79c48b5521 Remove width trick to use clear rect, fix #280 2017-02-08 10:27:51 +01:00
Francisco López
db8ad92e33 Remove map instance as an option in example 2017-01-30 12:23:25 +01:00
Francisco López
7a33d8a1de Remove map as an option to clarify 2017-01-30 10:05:58 +01:00
Mario de Frutos
d218c2da24 Removed contribution line 2017-01-25 10:52:38 +01:00
Mario de Frutos
cee1c7b16b Added contributing document 2017-01-25 10:52:04 +01:00
Francisco López
b9531f95ce Repair broken reference 2017-01-16 11:32:43 +01:00
xavijam
16bac52b91 Placeholder for new release 2016-12-12 16:21:29 +01:00
Javier Álvarez Medina
85d377e6b0 Merge pull request #277 from CartoDB/update-turbocarto
New Turbo-carto version
2016-12-12 16:17:17 +01:00
xavijam
ba156219fd New Turbo-carto version 2016-12-12 16:12:01 +01:00
Javier Álvarez Medina
2e1a020c3c Merge pull request #276 from CartoDB/issue-cartodb-10964
Don't throw an exception when a named map tries to set a new cartocss over the torque layer
2016-12-05 15:15:56 +01:00
xavijam
16564df47e Adding provider checker 2016-12-05 15:13:30 +01:00
xavijam
62fc84b9be Don't throw an exception when a named map tries to set a new cartocss 2016-12-05 13:31:59 +01:00
javi santana
65a115e9b1 Merge pull request #275 from CartoDB/docs-switch-to-builder
switched default tool from editor to builder in torque docs
2016-11-21 14:14:43 +01:00
csobier
94496795ee switched default tool from editor to builder in torque docs 2016-11-02 11:45:53 -04:00
csobier
47f02ce23d Merge pull request #274 from CartoDB/docs-fix-hyperlink
fixed broken hyperlinks that broke when the rebranding baseurl was ch…
2016-10-20 08:11:58 -04:00
csobier
56b7267ec5 fixed broken hyperlinks that broke when the rebranding baseurl was changed 2016-10-19 15:23:37 -04:00
Francisco López
fca222a05b Merge pull request #266 from bloomberg/master
Fix #263 Implementation of torque layer for OpenLayers for 3.17 or later.
2016-10-17 11:54:48 +02:00
Javier Álvarez Medina
01ffec1a34 Merge pull request #272 from CartoDB/setting-cartocss
Setting cartocss in internal style
2016-09-22 11:55:13 +02:00
xavijam
35251805bf Setting cartocss in internal style 2016-09-22 11:51:33 +02:00
Raul Ochoa
ddf487f56d Merge pull request #271 from CartoDB/update-dependencies
Pointing to a proper version in turbo-carto and d3 dependencies
2016-09-21 16:45:37 +02:00
xavijam
b614e25855 CARTO 2016-09-21 16:23:55 +02:00
xavijam
dbc5309ae0 CARTO 2016-09-21 16:20:16 +02:00
xavijam
c2d10feec9 Updated underscore version 2016-09-21 16:15:03 +02:00
xavijam
dfed86e7d5 Requesting turbo-carto 0.16.0 2016-09-21 16:06:42 +02:00
xavijam
0bfe358e39 New package version 2016-09-21 15:36:06 +02:00
xavijam
6be4d857e5 Pointing to a proper version in turbo-carto and d3 dependencies 2016-09-21 15:32:49 +02:00
Raul Ochoa
086da527bd Use a valid SPDX license expression 2016-08-03 17:55:54 +02:00
Raul Ochoa
8fe4c8f610 Fix deps 2016-08-03 17:50:17 +02:00
Carlos Matallín
8a14fe546a Update getting_started.md
/cc @csobier
2016-07-21 12:22:10 +02:00
javi
2bcb7d8036 updated turbo carto version 2016-07-20 16:07:45 +02:00
Anna Shchurova
46e9839da1 Fix #263 Implementation of torque layer for OpenLayers. Must be using OpenLayers 3.17 or later. 2016-07-18 12:42:01 -04:00
Carlos Matallín
4b6c70d462 Merge pull request #262 from CartoDB/docs-781
rebranding
2016-07-07 18:49:51 +02:00
Francisco Dans
b5a2e88f1c Merge pull request #261 from CartoDB/turbocarto
Turbo-carto support
2016-07-06 22:24:26 +02:00
Francisco Dans
f52a47a04e re-sets cartocss each time a tile is loaded 2016-07-06 20:55:57 +02:00
Francisco Dans
d1ab5620c6 adds explanation comment 2016-07-06 20:54:47 +02:00
Francisco Dans
bfc2489b5c reduces repetition, adds callback 2016-07-06 12:55:06 +02:00
Francisco Dans
4cd282a6d4 sets local cartocss on startup 2016-07-05 20:52:19 +02:00
Francisco Dans
3f4279a355 allows style setting sync when there is no turbo 2016-07-05 20:00:26 +02:00
csobier
d12d30cf82 updated any attribution example with rebranded name 2016-07-04 17:21:26 -04:00
Francisco Dans
933c95be9c adds custom datasource for torque 2016-07-04 18:50:37 +02:00
Francisco Dans
5f92bdc9da adds turbocarto integration 2016-07-04 18:50:22 +02:00
Francisco Dans
2377029350 sets cartocss once tiles have been loaded 2016-07-04 18:50:00 +02:00
Francisco Dans
0e9184e026 gets options only Map part of cartocss 2016-07-04 18:49:41 +02:00
Francisco Dans
1ff54b9018 passes tile object to layer 2016-07-04 18:49:12 +02:00
Francisco Dans
7f75022168 removes tiles init from tileloader 2016-07-04 18:48:49 +02:00
Francisco Dans
31af420c6d adds d3 and jenks 2016-07-04 18:48:31 +02:00
csobier
8184175642 fixed github hyperlink naming 2016-06-02 13:33:49 -04:00
csobier
80293501e5 reverted rebranded code, as instruted. Legacy cartodb code instead. Add applied ALL CAPS to rebranded name, as instructed 2016-05-31 12:28:33 -04:00
csobier
2628bcb9ff applied Docs 781 to torquejs docs 2016-05-26 11:27:52 -04:00
csobier
d196b617b8 Merge pull request #258 from CartoDB/docs-minor-edits
wordsmithed how libraries are generated
2016-03-18 08:34:36 -04:00
csobier
959e8c48dc wordsmithed how libraries are generated 2016-03-17 10:34:28 -04:00
csobier
31a81e760b Merge pull request #257 from CartoDB/docs-minor-edits
removed note about required libraries, from older branch
2016-03-17 09:06:31 -04:00
csobier
74a536da26 removed note about required libraries, from older branch 2016-03-17 09:02:01 -04:00
acanimal
178eb5700f Merge pull request #256 from CartoDB/pointcount
Added pointCount method
2016-02-24 15:00:12 +01:00
acanimal
b15585128f Added pointCount method for gmaps 2016-02-24 14:53:55 +01:00
acanimal
52cc4c663c Added pointCount method 2016-02-24 14:47:56 +01:00
Francisco Dans
30bd226d71 Merge pull request #254 from CartoDB/comp-ops
Allows all possible Canvas composite operations
2016-02-17 20:03:44 +01:00
Francisco Dans
9f759caaed Merge branch 'master' of github.com:CartoDB/torque into comp-ops 2016-02-17 20:00:39 +01:00
Francisco Dans
2fe9c737cd removes pos from rendertile args 2016-02-17 19:57:56 +01:00
Raul Ochoa
4cb2946486 Fix dev dependencies for tests
- Use fixed 1.3.0 version for node-qunit-phantomjs, which relies on
  phantomjs 1.x instead of 2.x
- Put back node-mapnik dep for acceptance tests
- Use minor versions for other dev deps
2016-02-17 19:20:38 +01:00
javi
4d69594f2a fixed version 2016-02-15 10:57:59 +01:00
javi
96adfc2836 update version 2016-02-15 10:47:57 +01:00
javi santana
99e8a242e4 Merge pull request #255 from CartoDB/key_fix
fixed ready event when using range rendering
2016-02-15 10:45:54 +01:00
javi
50789565c4 fixed ready event when using range rendering 2016-02-12 14:36:28 +01:00
Francisco Dans
12816745b5 reverts mix from another branch 2016-02-11 17:44:54 +01:00
Francisco Dans
1defdcba34 adds more comprehensive compop mappings 2016-02-09 12:56:01 +01:00
Francisco Dans
3e93e8f753 uses specified compop if it isn't in carto mapping 2016-02-09 12:20:11 +01:00
Francisco Dans
09ff7e273d Merge branch 'master' of github.com:CartoDB/torque 2016-01-19 16:42:14 +01:00
Carlos Matallín
3d290e259b Update getting_started.md 2016-01-19 12:14:55 +01:00
Carlos Matallín
2677f80814 Merge pull request #251 from CartoDB/newdocs
docs: add timeslider and interaction methods
2016-01-19 12:04:15 +01:00
Carlos Matallín
eb2e2c7b25 docs: add timeslider and interaction methods 2016-01-19 12:03:11 +01:00
Carlos Matallín
33396b4871 Merge pull request #248 from CartoDB/newdocs
split files
2016-01-19 11:00:27 +01:00
Carlos Matallín
4f2bc0b99a Merge branch 'newdocs' of github.com:CartoDB/torque into newdocs 2016-01-19 10:58:59 +01:00
Carlos Matallín
d9ae9b6ba5 Merge branch 'master' into newdocs 2016-01-19 10:58:41 +01:00
csobier
27e3480130 applied minor edits to getting started section, based on our style guide 2016-01-18 12:46:23 -05:00
Francisco Dans
6638a13e14 adds resources 2016-01-18 11:55:09 +01:00
Francisco Dans
abe1dd4570 getting started sguide 2016-01-18 11:46:59 +01:00
Francisco Dans
40044e5448 fires event when point added 2016-01-18 10:29:44 +01:00
Francisco Dans
01b30d18ca adds pos to parameters 2016-01-18 10:29:15 +01:00
Francisco Dans
3515046614 starts rewrite 2016-01-15 16:49:31 +01:00
Francisco Dans
b2b10868b0 removes tm sign 2016-01-14 17:18:45 +01:00
Francisco Dans
fd828bb6b3 puts the actual property names 2016-01-14 17:16:00 +01:00
Francisco Dans
4eb4bdbdc1 fixes url template 2016-01-14 17:15:45 +01:00
Francisco Dans
3a0220194b adds browser rendering note 2016-01-14 17:15:29 +01:00
Francisco Dans
a04f1a7d5b corrected, culled content in abstract 2016-01-14 12:49:10 +01:00
Francisco Dans
786af47be4 removes torque functions section 2016-01-14 12:20:28 +01:00
Francisco Dans
b0e04b7611 typo 2016-01-14 12:14:05 +01:00
Francisco Dans
cd9e1a3457 adds zoom and value to examples 2016-01-14 12:12:33 +01:00
Francisco Dans
990c52999a adjusts language of css description, removes duplicated information 2016-01-14 12:12:11 +01:00
Francisco Dans
2675df3526 indentation 2016-01-14 11:50:06 +01:00
Francisco Dans
093fc94076 adds a valid torque css example 2016-01-14 11:48:29 +01:00
Francisco Dans
0749bdd0e1 changes provider title 2016-01-14 11:48:17 +01:00
Francisco Dans
5c0232fa5f fixes hierarchy 2016-01-14 11:47:57 +01:00
Francisco Dans
2ced306f23 doc changes 2016-01-13 19:15:17 +01:00
csobier
56cfe309bd added Raul's edits 2015-12-30 09:21:30 -05:00
Carlos Matallín
4fe5cd2150 docs: torque functions 2015-12-16 11:46:32 +01:00
Raul Ochoa
7441a95b1a Stubs next version 2015-12-15 16:21:55 +01:00
Raul Ochoa
a3b07fc649 Regenerate dist files 2015-12-15 16:16:25 +01:00
Raul Ochoa
83cdcd11eb Merge pull request #247 from CartoDB/246-render-several-keys
Allow to render several keys/steps with a given range
2015-12-15 16:07:07 +01:00
Raul Ochoa
6172d9dd10 Bump version and update news with new functionality 2015-12-15 15:00:29 +01:00
Raul Ochoa
db961cf4b2 Add example for renderRange method 2015-12-15 14:57:48 +01:00
Raul Ochoa
d478fdc1b0 Adds key property to torque layers to keep property publicaly exposed 2015-12-15 14:53:46 +01:00
Carlos Matallín
77d9ac810c split files 2015-12-14 20:29:14 +01:00
Carlos Matallín
985c0b0eb5 split files 2015-12-14 20:19:38 +01:00
Carlos Matallín
31920d0d73 split files 2015-12-14 20:16:52 +01:00
Raul Ochoa
2d5542a28c Allow to render several keys/steps with a given range
- At low level point renderer now allows to receive several keys
 in renderTile.
- leaflet and gmaps layers expose renderRange(start, end) to be able
 to set and render a range of steps.

This closes #246
2015-12-14 10:56:07 +01:00
Raul Ochoa
5413f4cb82 Moves suite-bundle.js to dist dir inside test folder 2015-12-10 12:35:25 +01:00
Raul Ochoa
10d65267e6 Point travis badge to master branch 2015-12-02 15:20:30 +01:00
Raul Ochoa
08e59543dd Stubs next version 2015-11-25 17:13:36 +01:00
Raul Ochoa
29a05da8b8 Regenerate dist files 2015-11-25 17:07:13 +01:00
Raul Ochoa
b4ca93271b Bump version and add release notes about #243 2015-11-25 17:05:18 +01:00
Nicklas Gummesson
fd5c3aeec1 Merge pull request #243 from CartoDB/242-animator-sub-range
Implement allow custom animator range
2015-11-25 17:02:03 +01:00
Nicklas Gummesson
2bbf0576eb Rename class usage to match its definition 2015-11-25 16:10:14 +01:00
Nicklas Gummesson
b6169fb31a Implement possibility to set and remove a steps range 2015-11-24 18:34:46 +01:00
Raul Ochoa
6f35d6399a Stubs next version 2015-11-06 12:51:59 +01:00
Raul Ochoa
8f1bcde31f Release 2.13.0 2015-11-06 12:50:53 +01:00
Raul Ochoa
9d6a762f12 Regenerate bundles 2015-11-06 12:49:42 +01:00
javi santana
d6b15282b7 Merge pull request #234 from CartoDB/tilejson_extra_data
Pass extra_params to server
2015-10-30 18:03:47 +01:00
Paul Ramsey
1f88da6439 Pass extra_params to server 2015-10-30 06:11:19 -07:00
Francisco Dans
1bdaed7bcb adds dists for 2.12 2015-10-21 15:56:01 +02:00
Francisco Dans
5767ed7f35 updates news for 2.12 2015-10-21 15:55:48 +02:00
javi santana
9fe8d9b7f3 Merge pull request #225 from CartoDB/get_values
getValues function added
2015-10-02 18:53:21 +02:00
javi
dffb469c5c and more unused variables 2015-10-02 17:36:41 +02:00
javi
9f25dea8a6 removed more unused variables 2015-10-02 17:35:12 +02:00
javi
cf683238eb removed unnused var 2015-10-02 17:31:26 +02:00
javi
d4bbfb7431 documentation for getValues 2015-10-02 17:30:07 +02:00
javi
ff269a5ecf added getValues to fetch values for step. Also adds some signals needed to be able to use it and some fixes to the makefile 2015-10-02 17:29:53 +02:00
Francisco Dans
d7a0fa8ed1 Merge pull request #222 from CartoDB/tilejson
TileJSON generic provider
2015-10-01 19:29:22 +02:00
Francisco Dans
aa8c61b442 var name change 2015-10-01 18:46:33 +02:00
Francisco Dans
9cc7779858 one more test 2015-10-01 18:42:55 +02:00
Francisco Dans
3099b7b881 adds tilejson to suite 2015-10-01 18:42:42 +02:00
Francisco Dans
3eb011360b adds tilejson provider tests 2015-10-01 15:32:58 +02:00
Francisco Dans
b212913530 supports relative tile urls 2015-09-29 12:54:26 +02:00
Francisco Dans
e4aa398f6e more code stripping 2015-09-22 12:33:28 +02:00
Francisco Dans
e2461d6997 reverts windshaft provider 2015-09-22 11:51:48 +02:00
Francisco Dans
191e762d35 adds tilejson checking in gmaps 2015-09-22 11:50:38 +02:00
Francisco Dans
00e3ddfe99 uses tilejson provider when option is specified 2015-09-22 11:48:48 +02:00
Francisco Dans
ef03cbe98c passes tilejson example to different file 2015-09-22 11:47:53 +02:00
Francisco Dans
e4c61127e1 reverts navy example 2015-09-22 11:47:23 +02:00
Francisco Dans
a49bf13a9d reverts makefile 2015-09-22 11:46:05 +02:00
Francisco Dans
efa11680c4 strips tilejson from windshaft specific stuff 2015-09-22 11:42:57 +02:00
Francisco Dans
a88a0474d3 adds tilejson as a copy of windshaft 2015-09-22 11:32:55 +02:00
Francisco Dans
13affc5716 adds tilejson to list of providers 2015-09-22 11:32:29 +02:00
Francisco Dans
008c598e1c separates metadata getting functions 2015-09-21 18:03:16 +02:00
Francisco Dans
4527d4a300 admits tilejson option 2015-09-21 15:01:49 +02:00
Francisco Dans
334e2593d5 mods example 2015-09-18 14:53:48 +02:00
Francisco Dans
ff99d21c71 Merge pull request #217 from knownasilya/patch-1
Add default on* handlers for gmaps torque
2015-09-17 16:49:45 +02:00
Ilya Radchenko
57c6afb266 Add default on* handlers for gmaps torque
Should fix https://github.com/CartoDB/torque/issues/213
2015-09-08 15:59:55 -04:00
javi santana
a69527b637 CLA thing 2015-09-07 12:35:05 +02:00
javi santana
cd66a811d8 updated link to torque cubes reference, fixes #50 2015-08-25 10:06:01 +02:00
Francisco Dans
1ec0dc6585 Merge pull request #211 from CartoDB/fix-examples
Fixes/removes outdated examples
2015-08-05 17:15:22 +02:00
Francisco Dans
f02dd5a710 removes leaflet.html -- outdated 2015-08-05 16:22:07 +02:00
Francisco Dans
07d03735a7 removes wim.html -- outdated 2015-08-05 16:19:46 +02:00
Francisco Dans
87df24e914 fixes interaction examples 2015-08-05 16:18:33 +02:00
Francisco Dans
e68e7d3d37 actual dists 2015-08-05 15:56:36 +02:00
Francisco Dans
95453ab4b3 Merge branch 'master' of github.com:CartoDB/torque 2015-08-05 15:23:47 +02:00
Francisco Dans
84f7537969 removes js.gz 2015-08-05 15:23:18 +02:00
Francisco Dans
10589b2d28 bumps version in package.json 2015-08-05 15:22:49 +02:00
Francisco Dans
d4c994b6d2 bumps version in dist 2015-08-05 15:22:27 +02:00
Francisco Dans
e4a913cbad updates dist for 2.11.4 2015-08-05 15:21:41 +02:00
Francisco Dans
d5948c8009 updates news for 2.11.4 2015-08-05 15:20:58 +02:00
Francisco Dans
4385c6ad9a Merge pull request #209 from CartoDB/pause-fix
Checks if animator is running before resuming it on rescale
2015-08-05 14:49:14 +02:00
Francisco Dans
39773b3151 puts tests in module 2015-08-05 14:40:52 +02:00
Francisco Dans
3a10865f09 fixes range test 2015-08-05 14:36:59 +02:00
Francisco Dans
e46de301f5 reduces posibility of race condition 2015-08-05 14:27:29 +02:00
Francisco Dans
b3c8cd76c6 de-asyncs another test 2015-08-05 12:55:34 +02:00
Francisco Dans
5be36ca15a now I'm using only non-legacy 2015-08-05 12:49:02 +02:00
Francisco Dans
288321b383 uses legacy async testing 2015-08-05 12:35:06 +02:00
Francisco Dans
429e2d5852 de-asyncs a test 2015-08-05 12:34:55 +02:00
Francisco Dans
ea1d7dc48a comments out usual suspects to see what's up 2015-08-05 12:24:07 +02:00
Francisco Dans
2e03c784ae palos de ciego 2015-08-05 12:20:46 +02:00
Francisco Dans
f9bf4264b3 avoids race condition 2015-08-04 20:40:24 +02:00
Francisco Dans
388ef63f4d fixes loop test 2015-08-04 19:03:56 +02:00
Francisco Dans
66de9f9c49 second att 2015-08-04 16:51:42 +02:00
Francisco Dans
d5c3b0b5b4 migrates to container-based infrastructure 2015-08-04 16:44:55 +02:00
Francisco Dans
6f0ea37dbe Merge pull request #210 from CartoDB/animator-tests
Adds animator tests
2015-08-04 16:31:43 +02:00
Francisco Dans
8d1d55b7d1 adds test 2015-08-04 16:30:02 +02:00
Francisco Dans
ffdc70a60d Merge branch 'animator-tests' into pause-fix 2015-08-04 16:27:12 +02:00
Francisco Dans
83a622a3f0 removes console.log 2015-08-04 16:15:28 +02:00
Francisco Dans
efcfc13546 checks querydata 2015-08-04 16:09:43 +02:00
Francisco Dans
3a06914cc2 FIX ALL THE TESTS 2015-08-04 15:45:11 +02:00
Francisco Dans
88fe98447c adds sinon 2015-08-04 12:39:07 +02:00
Francisco Dans
f71c0c8473 Merge branch 'master' of github.com:CartoDB/torque into animator-tests 2015-08-04 12:38:01 +02:00
Francisco Dans
5017213a3b comments out test 2015-08-04 12:36:48 +02:00
Francisco Dans
ee43ef5fa1 updates deps 2015-08-04 12:33:39 +02:00
Francisco Dans
64e12f4ea8 adds animator tests 2015-08-04 12:32:36 +02:00
Francisco Dans
b419cb555f checks for provider on gmaps layer 2015-08-03 16:03:53 +02:00
Francisco Dans
579326954b resumes on rescale only if running 2015-08-03 16:03:23 +02:00
Francisco Dans
d41e42f838 Merge branch 'master' of github.com:CartoDB/torque 2015-08-03 11:30:11 +02:00
Francisco Dans
b2a1d6a0fa temp fix for header 2015-08-03 11:30:01 +02:00
Francisco Dans
5c2fc2a9a8 Merge pull request #207 from CartoDB/no-smooth
Removes jquery-smoothness and outdated examples
2015-08-03 11:23:20 +02:00
Francisco Dans
a2067687f9 removes out of date examples 2015-08-03 10:44:49 +02:00
Francisco Dans
2925f09df2 removes jquery-smoothness 2015-08-03 10:43:44 +02:00
Francisco Dans
973aa487dc Merge pull request #206 from CartoDB/header
Adds script to prepend a version header to uncompressed dists
2015-07-30 18:37:51 +02:00
Francisco Dans
28a11c99b7 makes header.js better 2015-07-30 17:19:10 +02:00
Francisco Dans
e015282f9c writes correct var 2015-07-30 17:07:24 +02:00
Francisco Dans
786d6c1edc adds add-header target to Makefile 2015-07-30 17:06:40 +02:00
Francisco Dans
df99c918d1 adds header to uncompressed dists 2015-07-30 16:58:17 +02:00
Francisco Dans
4744ccd661 add header file 2015-07-30 16:38:23 +02:00
Francisco Dans
9dcaf60d83 improves description 2015-07-30 16:38:09 +02:00
Francisco Dans
ddc9c2768f replaces Vizzuality with Cartodb 2015-07-30 16:01:57 +02:00
Francisco Dans
538f3e3912 amends torque version 2015-07-30 15:36:32 +02:00
Dani Carrión
be7046e5a0 Merge pull request #197 from CartoDB/providerload
renderer and provider are loaded before options.ready is defined, to prevent them from being called before their initialization
2015-06-23 16:24:55 +02:00
Dani Carrion
4ed644feaa renderer and provider are loaded before options.ready is defined, to prevent them from being called before their initialization 2015-06-23 14:43:44 +02:00
Francisco Dans
ebc1446063 Update NEWS 2015-06-15 15:43:30 +02:00
Francisco Dans
9cf50b9864 Merge pull request #195 from CartoDB/showstatic
Invalidates view on show() if steps are one
2015-06-15 14:56:58 +02:00
Francisco Dans
ed370dce54 uses if instead of falsy check 2015-06-15 14:29:22 +02:00
Francisco Dans
f621ae268b adds gmaps fix 2015-06-15 11:46:38 +02:00
Francisco Dans
9ca31c2963 redraws view on show if steps are one 2015-06-15 11:22:56 +02:00
Francisco Dans
cef13cbf37 prepares news for next release 2015-05-20 16:37:45 +02:00
Francisco Dans
2b12623b05 adds dist files for 2.11.3 2015-05-20 16:37:14 +02:00
Francisco Dans
c0b72b470c whoops 2015-05-20 16:36:15 +02:00
Francisco Dans
f63600ee28 updates NEWS 2015-05-20 16:32:52 +02:00
javi santana
f883575d10 Merge pull request #187 from knownasilya/patch-1
Fix issue with `_super` being removed from listeners
2015-05-18 14:56:55 +02:00
Francisco Dans
bf8cdf6e59 Update NEWS 2015-05-18 12:11:07 +02:00
Ilya Radchenko
999b4d49f4 Fix issue with _super being removed from listeners
See https://github.com/CartoDB/cartodb.js/issues/478#issuecomment-102415466 for more details.
2015-05-15 11:29:30 -04:00
Francisco Dans
321258a891 Merge pull request #186 from knownasilya/patch-1
Add getOpacity/setOpacity to canvaslayer
2015-05-14 11:47:55 +02:00
Ilya Radchenko
621fe55ea9 Fix comments 2015-05-12 11:58:56 -04:00
Ilya Radchenko
bc953b1185 Add getOpacity/setOpacity to canvaslayer 2015-05-12 11:57:46 -04:00
Francisco Dans
00a93d8c48 comments out stuff so tests pass 2015-05-11 10:24:37 +02:00
Francisco Dans
feccf2809b Merge pull request #183 from CartoDB/inertia
Matches inertia effect to Leaflet's
2015-05-06 10:59:49 +02:00
Francisco Dans
465c47e40d fixes wrong check position 2015-05-05 18:31:43 +02:00
Francisco Dans
147cdbf1b4 performs adjustment in the canvas layer instead of the torque layer 2015-05-05 18:28:22 +02:00
Francisco Dans
9ca2d5e774 updates news 2015-05-05 17:08:03 +02:00
Francisco Dans
3eef183945 sets the correct position of the canvas on each render 2015-05-05 16:56:55 +02:00
Francisco Dans
52b3521557 reverts last because it was useless 2015-05-05 16:56:28 +02:00
Francisco Dans
3476c74f1c listens to drag event instead of move to re-render 2015-05-05 15:48:40 +02:00
Francisco Dans
ad9f7c40b1 Merge pull request #182 from CartoDB/sprite-limit
More secure sprite limit
2015-05-05 15:14:20 +02:00
Francisco Dans
9c17d7a1bc uses capitals for constants like a normal human being 2015-05-05 15:09:07 +02:00
Francisco Dans
9486bd9667 uses radius from cartocss renderer 2015-05-05 14:47:54 +02:00
Francisco Dans
fa5791483e puts max radius as a constant 2015-05-05 12:56:37 +02:00
Francisco Dans
645da00ce1 limits the size of a point canvas too 2015-05-05 12:43:20 +02:00
Francisco Dans
4b10cc37d0 Merge pull request #181 from CartoDB/sprite-limit
Limits sprite radius to a maximum of 255
2015-05-04 14:52:07 +02:00
Francisco Dans
89b6819e53 adds NEWS entry for previous Firefox fix 2015-05-04 11:38:07 +02:00
Francisco Dans
adbeebb1c1 updates news 2015-05-04 11:36:52 +02:00
Francisco Dans
aabf0f234c limits sprite radius to 255 2015-05-04 11:35:30 +02:00
Francisco Dans
c14eed8756 adds beginnings of animator tests 2015-05-04 11:05:48 +02:00
Francisco Dans
581d7a337d Merge pull request #180 from CartoDB/firefox-flag
Doesn't add sprites to images flags if from Firefox
2015-05-04 09:57:21 +02:00
Francisco Dans
cdf3708a3c doesn't add flag if firefox 2015-04-30 13:00:34 +02:00
Francisco Dans
b8d8892951 updates dist for 2.11.2 2015-04-28 16:58:20 +02:00
Francisco Dans
b3c2af660c Update NEWS 2015-04-28 14:28:53 +02:00
Francisco Dans
70800798da Merge pull request #179 from CartoDB/clamped
Changes value array type to UInt8ClampedArray
2015-04-28 12:48:29 +02:00
Francisco Dans
a27960fbe7 adds stupid comma 2015-04-28 12:43:46 +02:00
Francisco Dans
3309b2cfad adds clamped type 2015-04-28 12:41:34 +02:00
Francisco Dans
c3b22324f1 uses clamped array for values 2015-04-28 12:41:25 +02:00
Francisco Dans
58345d248e Merge pull request #175 from CartoDB/named-maps
Throws error when calling setCartoCSS or setSQL with named maps
2015-04-24 10:34:27 +02:00
Francisco Dans
e98c518d09 updates API docs for named maps 2015-04-23 18:52:28 +02:00
Francisco Dans
5c8b3c0908 throws errors on named maps 2015-04-23 18:49:13 +02:00
Francisco Dans
d7a284082a Merge pull request #172 from CartoDB/timeslider-remove
Triggers the 'remove' event in onRemove
2015-04-20 19:03:42 +02:00
Francisco Dans
aaa8b819ed triggers remove from layer 2015-04-20 18:43:40 +02:00
Francisco Dans
36b4fa9c0c restores tileloaders 2015-04-20 18:43:24 +02:00
Francisco Dans
25e61e064f updates NEWS 2015-04-20 15:10:58 +02:00
Francisco Dans
caf21dce1f Merge branch 'master' of github.com:CartoDB/torque into timeslider-remove 2015-04-20 15:10:10 +02:00
Francisco Dans
c50b60db9c adds call to gmaps onRemove 2015-04-20 15:09:19 +02:00
Francisco Dans
e0c68c17e5 wololo 2015-04-20 14:59:41 +02:00
Francisco Dans
db914f65cf triggers remove event to get rid of timeslider' 2015-04-20 14:48:40 +02:00
Francisco Dans
6e73f8acea diff make 2015-04-20 14:47:47 +02:00
Francisco Dans
ee6b3e4c7f Update NEWS 2015-04-20 10:41:54 +02:00
Francisco Dans
995c209958 Merge pull request #170 from CartoDB/lg-errors
Error handling in torque
2015-04-15 15:23:58 +02:00
Francisco Dans
f775df9e9c only runs callback if it's been defined 2015-04-15 14:53:10 +02:00
Francisco Dans
27d983d646 uses self instead of bind 2015-04-15 11:54:23 +02:00
Francisco Dans
ee07260d7b documents error functoin 2015-04-15 11:27:10 +02:00
Francisco Dans
64d05276ae returns this on error function 2015-04-15 11:26:51 +02:00
Francisco Dans
d95399502c adds error handling to gmaps exampe 2015-04-15 11:21:17 +02:00
Francisco Dans
2ae4b71df6 fixes carto dependency on gmaps navy examples 2015-04-15 11:20:54 +02:00
Francisco Dans
2652f6c6d8 adds error handling to gmaps 2015-04-15 11:20:20 +02:00
Francisco Dans
8d8d65050d adds error handling to navy leaflet example 2015-04-15 10:59:09 +02:00
Francisco Dans
7626ebe3b6 runs callback where there are errors 2015-04-15 10:57:48 +02:00
Francisco Dans
3134aa828c adds error function to torqueLayer api 2015-04-15 10:56:48 +02:00
Francisco Dans
c04ab74a97 on errors, halts torque and displays them 2015-04-14 17:45:22 +02:00
javi santana
e96a1c7118 Merge pull request #163 from CartoDB/maps_api_template
add support for maps_api_template
2015-04-08 10:34:04 +02:00
Andy Eschbacher
8adc55fdd4 incorrect data option 2015-04-03 09:42:31 -04:00
Andy Eschbacher
e0e502a083 data option errors 2015-04-03 09:08:08 -04:00
Francisco Dans
9e7de2bcbd adds dist for 2.11.1 2015-04-01 14:43:03 +00:00
Francisco Dans
c3988b14a6 modifies news for 2.11.1 2015-04-01 14:42:07 +00:00
javi
a0417d8bc3 fixed user 2015-03-31 17:09:52 +02:00
javi
a434bd8640 add support for maps_api_template 2015-03-31 15:20:35 +02:00
Francisco Dans
8938c25280 Merge pull request #160 from CartoDB/addEventsDocs
Add events to docs
2015-03-31 12:01:02 +02:00
Andy Eschbacher
d5be1f115f updated events table 2015-03-30 15:45:40 -04:00
Andy Eschbacher
c058a55c58 Merge branch 'master' into addEventsDocs 2015-03-27 11:54:21 -04:00
Andy Eschbacher
e6c9f03e3d added more info 2015-03-20 15:22:34 -04:00
Andy Eschbacher
a935bfc93e added info about events 2015-03-20 15:14:55 -04:00
Francisco Dans
c3dd3af184 Merge pull request #156 from CartoDB/data-peek
Adds getValueForBbox
2015-03-17 14:59:50 +01:00
Francisco Dans
ce6351a2c4 Merge pull request #157 from CartoDB/fill-opacity
Allows for zero marker-fill-opacity
2015-03-17 12:01:09 +01:00
Francisco Dans
219a3f5888 removes unnecessary globalalpha set 2015-03-17 11:48:19 +01:00
Francisco Dans
a244fa183c passes logic upstairs 2015-03-17 11:44:44 +01:00
Francisco Dans
131f116487 prioritizes marker-opacity 2015-03-17 11:30:08 +01:00
Francisco Dans
f63b037d0e sets marker-opacity as preliminary global opacity value 2015-03-16 17:29:48 +01:00
Francisco Dans
35e28b22c7 uses for instead of while because ñiñiñi 2015-03-16 16:37:57 +01:00
Francisco Dans
73f8212c2f adds doc for getvalueforbbox 2015-03-13 19:08:43 +01:00
Francisco Dans
302ebf97cb updates NEWS 2015-03-13 19:02:44 +01:00
Francisco Dans
a2696195f4 Merge branch 'master' of github.com:CartoDB/torque into data-peek 2015-03-13 19:01:35 +01:00
Francisco Dans
e657f349df adds getValueForBBox for gmaps 2015-03-13 18:59:41 +01:00
Francisco Dans
567511f694 adds getValueForPos in gmaps 2015-03-13 18:48:08 +01:00
Francisco Dans
4fea2e32c1 adds data peek example 2015-03-11 18:56:37 +01:00
Francisco Dans
3ead777645 resets x value with each row 2015-03-11 18:56:11 +01:00
Francisco Dans
6232e16002 replaces falsy check with greater or equal 2015-03-11 18:01:38 +01:00
Francisco Dans
086c77c379 removes redundant decs 2015-03-11 17:45:59 +01:00
Francisco Dans
309bcb09f3 reverts Makefile to how it was 2015-03-11 17:39:22 +01:00
Francisco Dans
f04b149b23 adds getValueForBbox 2015-03-11 16:50:53 +01:00
Francisco Dans
8af1b8288b Merge pull request #153 from CartoDB/heat-gmaps
Adds support for heatmaps in Google Maps
2015-03-10 15:50:21 +01:00
Francisco Dans
d04eb9576c adds applyfilters call to gmaps layer 2015-03-10 12:48:32 +01:00
Raul Ochoa
d360dffe28 Fix reference to torque.providers.JsonArray provider 2015-03-10 11:47:08 +01:00
Raul Ochoa
80ef7bf727 Revert "Revert "Stubs next version""
This reverts commit c855c1c212.
2015-03-05 18:59:52 +01:00
Raul Ochoa
2af620ee74 Amend Release 2.11.0 2015-03-05 18:58:54 +01:00
Raul Ochoa
c855c1c212 Revert "Stubs next version"
This reverts commit 2c7f317af7.
2015-03-05 18:58:29 +01:00
Raul Ochoa
2c7f317af7 Stubs next version 2015-03-05 18:54:18 +01:00
Raul Ochoa
0a8708d044 Release 2.11.0 2015-03-05 18:53:24 +01:00
Raul Ochoa
734e6e119a Merge pull request #150 from CartoDB/149-windshaft-coordinates-type
Optional data type for coordinates in Windshaft provider
2015-03-05 17:58:59 +01:00
Raul Ochoa
3476c44efa Merge pull request #148 from CartoDB/147-no-edge-fix
Do not fix values in the edge
2015-03-05 17:58:40 +01:00
Raul Ochoa
fae792067e Windshaft provider accepts an optional data type for coordinates
closes #149
2015-03-05 16:25:38 +01:00
Raul Ochoa
204ed0903c Do not fix values in the edge. Closes #147 2015-03-05 15:34:50 +01:00
Raul Ochoa
a67d9df45a Merge pull request #145 from CartoDB/heatmaps-server
Changes to support server side heatmaps
2015-03-05 14:53:09 +01:00
Raul Ochoa
7359471605 Merge pull request #146 from CartoDB/acceptance-tests
Acceptance tests validating final image output
2015-03-05 14:47:15 +01:00
Raul Ochoa
a7ff63edfc Only try to render image sprite if icon exists 2015-03-04 19:36:25 +01:00
Raul Ochoa
7958c81c24 Reset icons to load counter and fire all icons loaded when any fails 2015-03-04 19:35:42 +01:00
Raul Ochoa
916871365f image.compare returns the % difference against the reference image
As canvas can differ from one implementation to another make tests
to have a tolerance to differences.
2015-03-04 18:53:06 +01:00
Raul Ochoa
ddffe412c6 Do not ignore results directory but png files within it 2015-03-04 18:26:52 +01:00
Raul Ochoa
ef2c90d28c Use cartodb's mapnik package 2015-03-04 18:20:58 +01:00
Raul Ochoa
81892a3231 Adds node-canvas build dependencies for travis 2015-03-04 17:57:25 +01:00
Raul Ochoa
2464e5cdf5 Adds canvas dependency 2015-03-04 17:52:34 +01:00
Raul Ochoa
0305d15106 point renderer acceptance tests
point renderer test helper to get a canvas from a windshaft torque json, cartocss, zxy and step
2015-03-04 17:26:05 +01:00
Raul Ochoa
149c741a03 acceptance tests now run on npm test 2015-03-04 17:24:37 +01:00
Raul Ochoa
49b093d3de Adds mapnik and qunit dependencies for acceptance tests
Basic test with canvas
abstracts mapnik comparison in image test helper
Ignore temporal images `results` directory
2015-03-04 17:23:08 +01:00
Raul Ochoa
286b23ebaf make all 2015-03-04 12:13:46 +01:00
Raul Ochoa
cfc702f98d renderSprite should take marker width as a point radius 2015-03-04 12:10:57 +01:00
Raul Ochoa
142ae1f528 make all: generate dist files 2015-03-04 11:08:46 +01:00
Raul Ochoa
1c25e13cec Rendering sprites for marker files scales the image to the size of the marker
renderPoint and renderRectangle keeps previous behaviour
2015-03-04 11:08:09 +01:00
Raul Ochoa
ac3df42b15 This gets interesting: renderTile defers the rendering until all icons are loaded 2015-03-04 11:05:26 +01:00
Raul Ochoa
c0131cdebf Icon preloading now downloads a set of URLs so if there are duplicated URLs it won't request the same image multiple times
Image loading can be provided and defaults to previous behaviour: client side `src = url`.
2015-03-04 11:03:46 +01:00
Raul Ochoa
656d082568 Trigger allIconsLoaded when there are no icons to load 2015-03-04 10:54:30 +01:00
Raul Ochoa
2ceeba0d82 Renderer.renderTile now accepts an optional {Function} callback parameter that will be called when it finish rendering 2015-03-04 10:49:52 +01:00
Raul Ochoa
f2a4c22dc7 Make torque_filters accept options param to add canvasClass 2015-03-04 10:46:02 +01:00
Andy Eschbacher
8bc49bcb3e added events -- tentative 2015-03-03 12:35:30 -05:00
Francisco Dans
043e7b0090 adds dists for 2.10.1 2015-03-02 17:35:13 +01:00
Francisco Dans
6c094e3ba9 bumps version to 2.10.1 2015-03-02 17:32:56 +01:00
Francisco Dans
cfe01c5dbe reflects changes for 2.10.1 in NEWS 2015-03-02 17:32:04 +01:00
Francisco Dans
7e43d0ecee Merge branch 'master' of github.com:CartoDB/torque 2015-03-02 17:26:15 +01:00
Francisco Dans
6ba2e42625 Merge pull request #138 from CartoDB/onesteppause
Makes sure that animation is paused when steps === one
2015-03-02 17:19:43 +01:00
Francisco Dans
ef42324b29 documents loop and cartocss options 2015-03-02 16:12:37 +01:00
javi santana
d744c9a497 Merge pull request #141 from abenrob/loop-pause-max
animation loop option to pause on max frame, not reset to beginning
2015-03-02 15:09:58 +01:00
abenrob
fa8a9bbc2b removed uneccesary frame update request 2015-03-02 14:09:09 +01:00
Francisco Dans
b605bd56ce Merge pull request #142 from CartoDB/anchor-middle
Fixes points position according to resolution
2015-03-02 14:07:02 +01:00
Francisco Dans
9a1571d79e precalculates anchor 2015-03-02 14:00:25 +01:00
Francisco Dans
dbc3c1c8f3 reverts navy_leaflet to norml 2015-03-02 12:46:20 +01:00
Francisco Dans
5006d6495d adds half the resolution size to x and y positions 2015-03-02 12:43:17 +01:00
Francisco Dans
d81bb5855c temporarily applies changes to leaflet examples 2015-03-02 12:18:38 +01:00
abenrob
d5e8007dce animation loop option to pause on max frame, not reset to beginning 2015-03-02 11:56:25 +01:00
Francisco Dans
767fae6272 adds start in animator rescale 2015-03-02 11:43:18 +01:00
Francisco Dans
5a27243f07 makes sure that animation is paused when steps is one 2015-02-26 16:10:18 +01:00
Raul Ochoa
ece11bb3f3 Release 2.10.0 2015-02-20 19:55:28 +01:00
Francisco Dans
fbac1510dc Merge pull request #129 from CartoDB/time-span
Makes getTimeSpan actually return an object
2015-02-17 17:00:26 +01:00
Francisco Dans
da7cf9d244 makes gettimespan actually return an object 2015-02-17 16:38:47 +01:00
Francisco Dans
db41e24b42 Merge pull request #128 from CartoDB/timetostep
Adds timeToStep() method
2015-02-17 16:22:24 +01:00
Raul Ochoa
847f3fc2f4 Merge pull request #114 from CartoDB/nodefix
Replaces direct call to document with abstraction
2015-02-17 15:01:23 +01:00
Francisco Dans
dfc8c982d9 adds timetostep method to torque layer 2015-02-17 14:39:17 +01:00
Francisco Dans
2c04ed0a40 Merge pull request #126 from CartoDB/updateAPIdoc
Added some missing methods
2015-02-16 09:51:49 +01:00
Andy Eschbacher
1d3e01a655 Added some missing methods 2015-02-14 14:00:50 -05:00
Francisco Dans
4ab654ac89 Update NEWS 2015-02-13 19:01:24 +01:00
Francisco Dans
dca842a08c Merge pull request #125 from CartoDB/named-params-fix
Adds params to request in torque named maps
2015-02-13 17:22:11 +01:00
Francisco Dans
8dffb1a8d2 OCD 2015-02-13 17:16:50 +01:00
Francisco Dans
ecb72d9e8a adds test for named maps params fix 2015-02-13 16:10:20 +01:00
Francisco Dans
da7144a7fd includes stat_tag correctly 2015-02-13 16:04:04 +01:00
Francisco Dans
81054b657a adds params to request in named maps 2015-02-13 15:52:03 +01:00
Francisco Dans
5ec6054487 Merge branch 'master' into nodefix
Conflicts:
	lib/torque/renderer/point.js
2015-02-10 18:27:50 +01:00
Francisco Dans
54f3fd2294 Merge pull request #123 from CartoDB/addtodoc
Added torqueLayer.setSQL to docs
2015-02-10 17:37:24 +01:00
Francisco Dans
959f216e82 removes console.log 2015-02-10 14:39:47 +01:00
Francisco Dans
d27f9b0919 Merge pull request #122 from CartoDB/cors-check
Checks for image-filters when preloading image-file
2015-02-10 14:17:52 +01:00
Francisco Dans
c82c55affd runs custom url qualifier if there is one provided 2015-02-10 13:30:35 +01:00
Francisco Dans
b4f5ae1667 Merge pull request #116 from CartoDB/cartocss_doc_fix
Removed buffer-size from doc
2015-02-10 12:30:03 +01:00
Francisco Dans
038777c8cc better error message for CORS disabled 2015-02-10 12:29:14 +01:00
Francisco Dans
45a3b57946 makes check for image-filters in all layers 2015-02-10 11:23:12 +01:00
Andy Eschbacher
830fc86eba Added torqueLayer.setSQL to docs 2015-02-09 11:56:48 -05:00
Francisco Dans
f0b7f09140 adds image filters check to add crossOrigin attribute or not 2015-02-09 17:49:23 +01:00
Francisco Dans
7d679cde70 Merge pull request #118 from CartoDB/clearCacheCSS
Clears cache when setCartoCSS is called
2015-02-05 18:35:05 +01:00
Francisco Dans
117f13c5e9 clears cache when setCartoCSS is called 2015-02-05 18:27:59 +01:00
Andy Eschbacher
a1d59585fb Removed buffer-size from doc 2015-02-05 09:58:16 -05:00
Francisco Dans
395edc39e0 checks itemstoload to be equal or lower than zero, just in case 2015-02-02 18:43:33 +01:00
Francisco Dans
9b421d7d7f Merge pull request #113 from CartoDB/loading-queue-fix
Fixes itemstoload negative issue
2015-02-02 18:20:39 +01:00
Francisco Dans
3f33dc3428 replaces direct call to document with abstraction 2015-02-02 18:20:11 +01:00
Francisco Dans
cd75867254 sums 1 to itemstoload previous to load trigger 2015-02-02 18:13:06 +01:00
Francisco Dans
7cb1d7b33b Merge pull request #111 from CartoDB/correctionfix
Substitutes inherited functions from leaflet to own correction
2015-02-02 18:04:49 +01:00
Francisco Dans
a56d4fe627 puts corrected x in local var 2015-02-02 18:00:57 +01:00
Francisco Dans
d7ebab04d5 substitutes inherited functions from leaflet to own correction 2015-02-02 17:57:13 +01:00
Andy Eschbacher
94b58126df Merge pull request #90 from CartoDB/addCartocssDoc
Add cartocss doc
2015-02-02 09:42:11 -05:00
Francisco Dans
f65fae5639 Merge pull request #109 from CartoDB/gradient-caching-fix
Allowing gradient to update live
2015-01-29 15:54:32 +01:00
Francisco Dans
9fcddf9ec3 Merge pull request #107 from CartoDB/image-size
Corrects the size of the image asset to renderer
2015-01-29 14:34:54 +01:00
Francisco Dans
dc81b7a335 adds smarter hashing for gradients and style 2015-01-29 13:19:51 +01:00
Francisco Dans
aca16f2549 updates css when step is 1 2015-01-29 13:19:13 +01:00
Francisco Dans
42ef4bcd48 corrects the size of the image asset to renderer 2015-01-28 19:32:36 +01:00
Francisco Dans
1696005d77 Merge pull request #101 from CartoDB/colorize
Begins support for image-filters
2015-01-21 16:46:23 +01:00
Francisco Dans
446bd632c8 removes a bit more unneeded code from simpleheat 2015-01-21 16:36:04 +01:00
Francisco Dans
4e5b1929c7 caches gradient generation 2015-01-21 16:24:40 +01:00
Francisco Dans
47a14ed7d3 - pos from renderTiles 2015-01-21 16:12:15 +01:00
Francisco Dans
135400043e removes unnecessary args 2015-01-21 16:10:20 +01:00
Francisco Dans
4bf358f59e changes name from simpleheat to torque_filters 2015-01-21 16:08:04 +01:00
Francisco Dans
b73d687141 removes unnecessary code in simpleheat 2015-01-21 15:55:20 +01:00
Francisco Dans
cd7146f6e0 uses alpha specified in style for image assets 2015-01-21 15:38:58 +01:00
Francisco Dans
ea79f007a2 passes style to sprite rendering 2015-01-21 15:38:18 +01:00
Francisco Dans
fdc63548d4 usses applyfilters instead of event 2015-01-21 15:37:47 +01:00
Francisco Dans
b2c37b1310 adds event call to leaflet 2015-01-20 18:24:51 +01:00
Francisco Dans
d85189b7f4 adds simpleheat, modifies draw method to avoid processing data 2015-01-20 18:24:06 +01:00
Francisco Dans
0ea62d36e7 fixes problem in img name mismatch 2015-01-20 18:23:24 +01:00
Francisco Dans
24413a706f adds colorization for whole canvas 2015-01-20 18:22:58 +01:00
Francisco Dans
38f0e3d814 ego 2015-01-19 15:23:51 +01:00
Francisco Dans
fe09fe9e0c updates vendor carto dist 2015-01-19 15:23:20 +01:00
Francisco Dans
8ee054fa89 Merge pull request #94 from CartoDB/empty-icons
Empties _icons every time Torque re-preloads them
2015-01-19 12:31:05 +01:00
Francisco Dans
9c5859be41 empties _icons every time preload is run, assumes _icons is empty 2015-01-16 11:36:06 +01:00
Andy Eschbacher
3b50c7cf5d Added ref for CartoCSS 2015-01-15 15:35:53 -05:00
Andy Eschbacher
30c2bf6a47 Initial commit 2015-01-15 15:34:47 -05:00
Francisco Dans
4bc2a8492a Merge pull request #87 from CartoDB/image-fallback
Makes drawing elements always fallback to rendering points or rectangles
2015-01-15 18:46:09 +01:00
Francisco Dans
019ac452f0 inits _icons before setCartoCSS is called 2015-01-15 18:15:10 +01:00
Francisco Dans
26f185aa09 removes carto script call from examples 2015-01-15 18:14:33 +01:00
Francisco Dans
508b75e4da moves icon preloading to setShader 2015-01-15 17:52:17 +01:00
Francisco Dans
70a55ebfba makes it always fallback to rendering points or rectangles 2015-01-15 17:39:59 +01:00
Francisco Dans
bf25f76761 updates NEWS with 2.8 changes 2015-01-14 17:00:21 +01:00
Francisco Dans
1449a9df85 adds dist files for 2.8 2015-01-14 17:00:00 +01:00
Francisco Dans
7826a914d9 Merge pull request #86 from CartoDB/makefile-full
Changes makefile to add a full uncompressed dist
2015-01-14 14:51:21 +01:00
Francisco Dans
e649d785f3 Revert "updates dist for release, adds uncompressed full dist"
This reverts commit cadbb8fd72.
2015-01-14 14:44:41 +01:00
Francisco Dans
cadbb8fd72 updates dist for release, adds uncompressed full dist 2015-01-14 14:03:00 +01:00
Francisco Dans
b5acfb30a7 updates examples to use uncompressed full 2015-01-14 14:02:31 +01:00
Francisco Dans
cb7c7da7c5 adds uncompressed full dist 2015-01-14 13:57:51 +01:00
Francisco Dans
93e0b8129b Merge pull request #84 from CartoDB/coord-wrap
Adjusts tile xy value when coordinates are out of bounds
2015-01-13 15:32:37 +01:00
Francisco Dans
9a0151d717 Merge pull request #63 from CartoDB/example-additions
Example additions
2015-01-12 18:04:29 +01:00
Francisco Dans
dac3246fcd style 2015-01-12 16:53:01 +01:00
Francisco Dans
8d8dbb29b4 changes test forming windshaft url 2015-01-12 16:47:51 +01:00
Francisco Dans
1e106b23b9 removes adjusting methods from mixin (this time for realsies) 2015-01-12 16:28:45 +01:00
Francisco Dans
bfcd6ca06f url always uses corrected values from tile object 2015-01-12 16:23:38 +01:00
Francisco Dans
1c0057b0ed adds corrected tile values to tile object in order to for the URL correctly 2015-01-12 16:22:47 +01:00
Francisco Dans
1a2c6f2ab0 removes adjust operations from tileloader_mixin 2015-01-12 16:21:52 +01:00
Francisco Dans
fbeddab4a3 Merge branch 'master' of github.com:CartoDB/torque into coord-wrap 2015-01-12 11:05:46 +01:00
Francisco Dans
17840c4403 Merge pull request #80 from CartoDB/svg-fix
Fixes svg drawing functionality
2015-01-08 18:50:18 +01:00
Francisco Dans
224c14783f style 2015-01-08 18:33:12 +01:00
Francisco Dans
b95ab3bac5 refactors icon preloading to its own private method 2015-01-08 18:27:53 +01:00
Francisco Dans
45e577c872 defaults to point rendering in case marker-file errors, shows error in console 2015-01-08 18:09:55 +01:00
Francisco Dans
434684df09 removes a check I added previously by accident 2015-01-08 17:57:12 +01:00
Francisco Dans
4d596066df changes carto dependency declaration to master 2015-01-08 17:55:10 +01:00
Francisco Dans
368f5b1526 merge 2015-01-08 16:51:21 +01:00
Francisco Dans
b295bdbd5f fixes method call 2015-01-08 16:45:09 +01:00
Francisco Dans
d1c224ff13 preloads all icons before the animation is started 2015-01-08 16:25:42 +01:00
Francisco Dans
8241bd6c8c removes getIcons call 2015-01-08 16:25:02 +01:00
Francisco Dans
91b056329b removes regex icon parsing 2015-01-08 15:54:42 +01:00
Francisco Dans
37c35732d7 loads async icon files as they are needed 2015-01-07 17:42:50 +01:00
Francisco Dans
1113a100d1 gets icon filenames via regex 2015-01-07 17:42:19 +01:00
Francisco Dans
06ed46f6b8 extends events in pointrenderer 2015-01-07 17:41:37 +01:00
Francisco Dans
d98402d9cd adds icon preload before animation 2015-01-05 16:54:53 +01:00
Francisco Dans
5dc39a5e32 only start animator if assets are ready 2015-01-05 16:54:14 +01:00
Francisco Dans
3c41470d7a adjusts tile xy value when coordinates are out of bounds 2015-01-05 11:15:18 +01:00
Francisco Dans
c21c715bf4 removes img name declaration from condition statement 2015-01-02 10:43:43 +01:00
Francisco Dans
e9cece69bd 🐴 2014-12-30 15:37:10 +01:00
Francisco Dans
a30d5fc269 changes drawImage call to align svgs centre-centre 2014-12-30 15:33:40 +01:00
Francisco Dans
fc3584b01f saves svg icons in an object instead of loading them with every draw 2014-12-30 12:42:46 +01:00
Francisco Dans
2f8443fe6e removes ratio, since it'll never be called 2014-12-30 11:00:26 +01:00
Francisco Dans
ead86bad00 makes image object instead of passing just the name 2014-12-30 10:53:46 +01:00
Raul Ochoa
3cdd89ab24 Build latest changes 2014-12-19 11:01:04 +01:00
javi
731206090a fixed property name 2014-12-19 10:12:40 +01:00
javi
2074a720a1 merged 2014-12-19 09:33:31 +01:00
javi
1d5414a31d updated version 2014-12-19 09:32:35 +01:00
javi
994aeedf95 replaces line-color with marke prefixed 2014-12-19 09:30:43 +01:00
javi
05e1137fe9 added marker-width 2014-12-19 08:00:37 +01:00
javi
b4330f68a6 fixed stroke 2014-12-19 08:00:19 +01:00
Raul Ochoa
728136d964 Merge pull request #75 from CartoDB/74-instantiate-windshaft-provider-without-fetchmap
Adds option to not fetch map when instantiating a windshaft provider
2014-12-18 18:40:16 +01:00
Raul Ochoa
9c5c290c4e Adds option to not fetch map when instantiating a windshaft provider.
Closes #74
2014-12-18 17:10:37 +01:00
andrewxhill
9e5a44ab13 more torque examples 2014-12-05 17:35:00 -05:00
andrewxhill
dcbe303b4e new static examples 2014-12-05 17:01:24 -05:00
128 changed files with 75896 additions and 27244 deletions

2
.gitignore vendored
View File

@ -2,4 +2,4 @@
.DS_Store .DS_Store
*.swp *.swp
node_modules node_modules
test/suite-bundle.js test/dist/suite-bundle.js

View File

@ -1,3 +1,18 @@
language: node_js language: node_js
node_js: node_js:
- "0.10" - '10'
before_install:
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- pkg-config
- libcairo2-dev
- libpango1.0-dev
- libjpeg8-dev
- libgif-dev
- gcc-4.9
- g++-4.9
sudo: false

11
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,11 @@
Contributing
---
The issue tracker is at [github.com/CartoDB/torque](https://github.com/CartoDB/torque).
We love pull requests from everyone, see [Contributing to Open Source on GitHub](https://guides.github.com/activities/contributing-to-open-source/#contributing).
## Submitting Contributions
* You will need to sign a Contributor License Agreement (CLA) before making a submission. [Learn more here](https://carto.com/contributions).

View File

@ -1,4 +1,4 @@
Copyright (c) 2011, Vizzuality Copyright (c) 2015, CartoDB
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@ -10,8 +10,8 @@ modification, are permitted provided that the following conditions are met:
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software 3. All advertising materials mentioning features or use of this software
must display the following acknowledgement: must display the following acknowledgement:
This product includes software developed by Vizzuality. This product includes software developed by CartoDB.
4. Neither the name of Vizzuality nor the 4. Neither the name of CartoDB nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.

View File

@ -5,16 +5,18 @@ BROWSERIFY=./node_modules/browserify/bin/cmd.js
JS_CLIENT_FILES= lib/torque/*.js \ JS_CLIENT_FILES= lib/torque/*.js \
lib/torque/renderer/*.js \ lib/torque/renderer/*.js \
lib/torque/gmaps/*.js \ lib/torque/gmaps/*.js \
lib/torque/ol/*.js \
lib/torque/leaflet/leaflet_tileloader_mixin.js \ lib/torque/leaflet/leaflet_tileloader_mixin.js \
lib/torque/leaflet/canvas_layer.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 all: dist/torque.js dist/torque.full.js add-header
dist/torque.full.js: dist_folder dist/torque.uncompressed.js dist/torque.full.uncompressed.js: dist_folder dist/torque.uncompressed.js
$(BROWSERIFY) lib/torque/index.js --standalone torque > dist/_torque.full.js $(BROWSERIFY) lib/torque/index.js --standalone torque > dist/torque.full.uncompressed.js
$(UGLIFYJS) dist/_torque.full.js > dist/torque.full.js
rm -rf dist/_torque.full.js dist/torque.full.js: dist_folder dist/torque.full.uncompressed.js
$(UGLIFYJS) dist/torque.full.uncompressed.js > dist/torque.full.js
dist/torque.uncompressed.js: dist_folder $(JS_CLIENT_FILES) dist/torque.uncompressed.js: dist_folder $(JS_CLIENT_FILES)
$(BROWSERIFY) lib/torque/index.js --no-bundle-external --standalone torque > dist/torque.uncompressed.js $(BROWSERIFY) lib/torque/index.js --no-bundle-external --standalone torque > dist/torque.uncompressed.js
@ -25,12 +27,31 @@ dist/torque.js: dist_folder dist/torque.uncompressed.js
dist_folder: dist_folder:
mkdir -p dist mkdir -p dist
test_dist_folder:
mkdir -p test/dist
dist: dist_folder dist/torque.js dist: dist_folder dist/torque.js
prepare-test-suite: clean-results:
browserify test/suite.js > test/suite-bundle.js -@rm test/results/*.png
clean: add-header:
node lib/header.js
prepare-test-suite: test_dist_folder
$(BROWSERIFY) test/suite.js > test/dist/suite-bundle.js
test: prepare-test-suite
@echo "***tests***"
./node_modules/node-qunit-phantomjs/bin/node-qunit-phantomjs test/suite.html
test-acceptance: clean-results
@echo "***acceptance***"
./node_modules/.bin/qunit -c lib/torque/ -t `find test/acceptance/ -name "*.js"`
test-all: test test-acceptance
clean:
rm -rf dist rm -rf dist
.PHONY: clean dist_folder .PHONY: clean dist_folder

118
NEWS
View File

@ -1,3 +1,121 @@
3.1.2 (2019-mm-dd)
3.1.1 (2019-06-24)
- Fixed reading undefined layer #306
3.1.0 (2019-04-02)
- Upgrade canvas to version 2.4.1
3.0.0 (2019-03-29)
- Drop support for Node.js 6 and 8
- Handle exception: Image given has not completed loading
2.17.1 (2019-01-23)
- Upgrade deps:
- turbo-carto@0.21.1
- Upgrade devel deps:
- browserify@16.2.3
- qunitz@0.7.7
- request@2.88.0
- uglify-js@3.4.9
2.17.0 (2018-11-21)
- Use our current fork of mapnik while testing
- Add support for Node 8 & 10
- Support package-lock.json file
v2.16.5
-
v2.16.4
-
2.16.2
- Re-publish version
2.16.1
- Remove width trick to use clear rect #280
- Map option reference broken gmaps #279
2.16.0
- Updated Turbo-carto dependency to version 0.19.0.
2.15.1
- Fixed ready event then rendering more than one step
2.15.0
- Allow to render several steps at the same time (#247)
2.14.0
- Allow custom animator range (#243)
2.13.0
- Pass extra_params to server (#234)
2.12.0
- Added TileJSON provider
- Added getValues to fetch values for step
- Improved reference/api documentation
- Removed out of date examples
2.11.4
- Static torque maps now draw correctly when unhiding them
- Fixed animation always playing when rescaling
- Added animator tests
2.11.3
- Limited sprite radius to a maximum of 255px
- Fixed custom marker-file functionality in Firefox
- Fixed inertia mismatch of Torque's canvas layer
- Added opacity get/setter to canvas layer in Google Maps
- Fixed issue with `_super` being removed from listeners
2.11.2
- Added error handling to Torque
- Fixed 'remove' event triggering when removing a Torque layer.
- Value is now capped at 255 instead of performing modulo on higher values.
2.11.1
- Adapts usage of marker-opacity to Mapnik's functionality
- Added getValueForBBox to TorqueLayer's API
2.11.0
- Do not fix values in the edge (#147)
- Windshaft provider accepts an optional data type for coordinates (#149)
- Acceptance tests
- renderTile accepts a callback to be called when rendering finishes
- tile rendering deferred until all assets are loaded
- sprite rendering now scales source to marker dimensions
- Filters accept a canvas class
2.10.1
- Adjusted point position taking resolution into account
- Changed loop: false to pause animation at last frame
- On torque-frame-count: 1, always pause for better performance
- Fixes getTimeSpan
2.10.0
- Adds timetostep method to torque layer
- Function qualifyURL can be provided to not rely on document's one
2.9.0
- Added heatmaps
- Added image-filters
- Solved problem of CSS not updating the vis until reloaded
- Improved out of bounds correction function
- Fixed image-asset sizing
- Fixed items to load counter being sometimes negative
2.8.0
- Supports use of external image markers via marker-file
- Fixes Torque tiles not rendering outside normal lat/lng ranges.
- Fixes marker image default pivot point
- Fixes ghost frame being added to the end of animation
- Moved to browserify for compatibility with Node.js
2.7.1
- Fix renderer not rendering marker-lines
2.7.0
- Adds option to not fetch map when instantiating a windshaft provider (#74)
2.6.1 2.6.1
- Fix marker fill opacity (#72) - Fix marker fill opacity (#72)

View File

@ -1,7 +1,7 @@
Torque Torque
== ==
[![Build Status](https://travis-ci.org/CartoDB/torque.svg)](https://travis-ci.org/CartoDB/torque) [![Build Status](https://travis-ci.org/CartoDB/torque.svg?branch=master)](https://travis-ci.org/CartoDB/torque)
Render big, timeseries data in the client. Uses CartoDB to generate a datacube format. For a brief introduction to the format and methods, see our [presentation slides](http://gijs.github.com/images/cartodb_datacubes.pdf) Render big, timeseries data in the client. Uses CartoDB to generate a datacube format. For a brief introduction to the format and methods, see our [presentation slides](http://gijs.github.com/images/cartodb_datacubes.pdf)
@ -17,20 +17,20 @@ Have fun!
Torque lets you render big, timeseries or categorical data in the client. This is useful for many modern applications that need more than just a static map. Early versions of Torque have been used to visualize human movement, Twitter activity, biodiversity data, and many more large-scale datasets. Torque lets you render big, timeseries or categorical data in the client. This is useful for many modern applications that need more than just a static map. Early versions of Torque have been used to visualize human movement, Twitter activity, biodiversity data, and many more large-scale datasets.
The library uses CartoDB to generate a [layercube]() format. For a brief introduction to the format and methods, see our [presentation slides](http://gijs.github.com/images/cartodb_datacubes.pdf). If you are not using CartoDB to host your data, you can modify the input parameters to point toward any layercube service. The library uses CartoDB to generate a [layercube](https://github.com/CartoDB/tilecubes/blob/master/2.0/spec.md) format. For a brief introduction to the format and methods, see our [presentation slides](http://gijs.github.com/images/cartodb_datacubes.pdf). If you are not using CartoDB to host your data, you can modify the input parameters to point toward any layercube service.
### Getting started ### Getting started
The simplest way to use a visualization with Torque is... The simplest way to use a visualization with Torque is...
<div class="margin20"></div> #### Create a simple Torque visualization
<div class="code_title">Create a simple Torque visualization</div>
``` javascript ```javascript
... ...
<body> <body>
<div id="map"></div> <div id="map"></div>
</body> ...
... <script>
// define the torque layer style using cartocss // define the torque layer style using cartocss
var CARTOCSS = [ var CARTOCSS = [
'Map {', 'Map {',
@ -74,9 +74,10 @@ The simplest way to use a visualization with Torque is...
}); });
torqueLayer.addTo(map); torqueLayer.addTo(map);
torqueLayer.play() torqueLayer.play()
</script>
</body>
```
<script>
```
[Grab the complete example source code](https://github.com/CartoDB/torque/blob/master/examples/navy_leaflet.html) [Grab the complete example source code](https://github.com/CartoDB/torque/blob/master/examples/navy_leaflet.html)
<div class="margin20"></div> <div class="margin20"></div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -1,544 +0,0 @@
/*! jQuery UI - v1.10.2 - 2013-03-29
* http://jqueryui.com
* Includes: jquery.ui.core.css, jquery.ui.slider.css
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
/* Layout helpers
----------------------------------*/
.ui-helper-hidden {
display: none;
}
.ui-helper-hidden-accessible {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.ui-helper-reset {
margin: 0;
padding: 0;
border: 0;
outline: 0;
line-height: 1.3;
text-decoration: none;
font-size: 100%;
list-style: none;
}
.ui-helper-clearfix:before,
.ui-helper-clearfix:after {
content: "";
display: table;
border-collapse: collapse;
}
.ui-helper-clearfix:after {
clear: both;
}
.ui-helper-clearfix {
min-height: 0; /* support: IE7 */
}
.ui-helper-zfix {
width: 100%;
height: 100%;
top: 0;
left: 0;
position: absolute;
opacity: 0;
filter:Alpha(Opacity=0);
}
.ui-front {
z-index: 100;
}
/* Interaction Cues
----------------------------------*/
.ui-state-disabled {
cursor: default !important;
}
/* Icons
----------------------------------*/
/* states and images */
.ui-icon {
display: block;
text-indent: -99999px;
overflow: hidden;
background-repeat: no-repeat;
}
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.ui-slider {
position: relative;
text-align: left;
}
.ui-slider .ui-slider-handle {
position: absolute;
z-index: 2;
width: 1.2em;
height: 1.2em;
cursor: default;
}
.ui-slider .ui-slider-range {
position: absolute;
z-index: 1;
font-size: .7em;
display: block;
border: 0;
background-position: 0 0;
}
/* For IE8 - See #6727 */
.ui-slider.ui-state-disabled .ui-slider-handle,
.ui-slider.ui-state-disabled .ui-slider-range {
filter: inherit;
}
.ui-slider-horizontal {
height: .8em;
}
.ui-slider-horizontal .ui-slider-handle {
top: -.3em;
margin-left: -.6em;
}
.ui-slider-horizontal .ui-slider-range {
top: 0;
height: 100%;
}
.ui-slider-horizontal .ui-slider-range-min {
left: 0;
}
.ui-slider-horizontal .ui-slider-range-max {
right: 0;
}
.ui-slider-vertical {
width: .8em;
height: 100px;
}
.ui-slider-vertical .ui-slider-handle {
left: -.3em;
margin-left: 0;
margin-bottom: -.6em;
}
.ui-slider-vertical .ui-slider-range {
left: 0;
width: 100%;
}
.ui-slider-vertical .ui-slider-range-min {
bottom: 0;
}
.ui-slider-vertical .ui-slider-range-max {
top: 0;
}
/* Component containers
----------------------------------*/
.ui-widget {
font-family: Verdana,Arial,sans-serif;
font-size: 1.1em;
}
.ui-widget .ui-widget {
font-size: 1em;
}
.ui-widget input,
.ui-widget select,
.ui-widget textarea,
.ui-widget button {
font-family: Verdana,Arial,sans-serif;
font-size: 1em;
}
.ui-widget-content {
border: 1px solid #aaaaaa;
background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;
color: #222222;
}
.ui-widget-content a {
color: #222222;
}
.ui-widget-header {
border: 1px solid #aaaaaa;
background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;
color: #222222;
font-weight: bold;
}
.ui-widget-header a {
color: #222222;
}
/* Interaction states
----------------------------------*/
.ui-state-default,
.ui-widget-content .ui-state-default,
.ui-widget-header .ui-state-default {
border: 1px solid #d3d3d3;
background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;
font-weight: normal;
color: #555555;
}
.ui-state-default a,
.ui-state-default a:link,
.ui-state-default a:visited {
color: #555555;
text-decoration: none;
}
.ui-state-hover,
.ui-widget-content .ui-state-hover,
.ui-widget-header .ui-state-hover,
.ui-state-focus,
.ui-widget-content .ui-state-focus,
.ui-widget-header .ui-state-focus {
border: 1px solid #999999;
background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;
font-weight: normal;
color: #212121;
}
.ui-state-hover a,
.ui-state-hover a:hover,
.ui-state-hover a:link,
.ui-state-hover a:visited {
color: #212121;
text-decoration: none;
}
.ui-state-active,
.ui-widget-content .ui-state-active,
.ui-widget-header .ui-state-active {
border: 1px solid #aaaaaa;
background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;
font-weight: normal;
color: #212121;
}
.ui-state-active a,
.ui-state-active a:link,
.ui-state-active a:visited {
color: #212121;
text-decoration: none;
}
/* Interaction Cues
----------------------------------*/
.ui-state-highlight,
.ui-widget-content .ui-state-highlight,
.ui-widget-header .ui-state-highlight {
border: 1px solid #fcefa1;
background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;
color: #363636;
}
.ui-state-highlight a,
.ui-widget-content .ui-state-highlight a,
.ui-widget-header .ui-state-highlight a {
color: #363636;
}
.ui-state-error,
.ui-widget-content .ui-state-error,
.ui-widget-header .ui-state-error {
border: 1px solid #cd0a0a;
background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;
color: #cd0a0a;
}
.ui-state-error a,
.ui-widget-content .ui-state-error a,
.ui-widget-header .ui-state-error a {
color: #cd0a0a;
}
.ui-state-error-text,
.ui-widget-content .ui-state-error-text,
.ui-widget-header .ui-state-error-text {
color: #cd0a0a;
}
.ui-priority-primary,
.ui-widget-content .ui-priority-primary,
.ui-widget-header .ui-priority-primary {
font-weight: bold;
}
.ui-priority-secondary,
.ui-widget-content .ui-priority-secondary,
.ui-widget-header .ui-priority-secondary {
opacity: .7;
filter:Alpha(Opacity=70);
font-weight: normal;
}
.ui-state-disabled,
.ui-widget-content .ui-state-disabled,
.ui-widget-header .ui-state-disabled {
opacity: .35;
filter:Alpha(Opacity=35);
background-image: none;
}
.ui-state-disabled .ui-icon {
filter:Alpha(Opacity=35); /* For IE8 - See #6059 */
}
/* Icons
----------------------------------*/
/* states and images */
.ui-icon {
width: 16px;
height: 16px;
}
.ui-icon,
.ui-widget-content .ui-icon {
background-image: url(images/ui-icons_222222_256x240.png);
}
.ui-widget-header .ui-icon {
background-image: url(images/ui-icons_222222_256x240.png);
}
.ui-state-default .ui-icon {
background-image: url(images/ui-icons_888888_256x240.png);
}
.ui-state-hover .ui-icon,
.ui-state-focus .ui-icon {
background-image: url(images/ui-icons_454545_256x240.png);
}
.ui-state-active .ui-icon {
background-image: url(images/ui-icons_454545_256x240.png);
}
.ui-state-highlight .ui-icon {
background-image: url(images/ui-icons_2e83ff_256x240.png);
}
.ui-state-error .ui-icon,
.ui-state-error-text .ui-icon {
background-image: url(images/ui-icons_cd0a0a_256x240.png);
}
/* positioning */
.ui-icon-blank { background-position: 16px 16px; }
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-on { background-position: -96px -144px; }
.ui-icon-radio-off { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
/* Misc visuals
----------------------------------*/
/* Corner radius */
.ui-corner-all,
.ui-corner-top,
.ui-corner-left,
.ui-corner-tl {
border-top-left-radius: 4px;
}
.ui-corner-all,
.ui-corner-top,
.ui-corner-right,
.ui-corner-tr {
border-top-right-radius: 4px;
}
.ui-corner-all,
.ui-corner-bottom,
.ui-corner-left,
.ui-corner-bl {
border-bottom-left-radius: 4px;
}
.ui-corner-all,
.ui-corner-bottom,
.ui-corner-right,
.ui-corner-br {
border-bottom-right-radius: 4px;
}
/* Overlays */
.ui-widget-overlay {
background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;
opacity: .3;
filter: Alpha(Opacity=30);
}
.ui-widget-shadow {
margin: -8px 0 0 -8px;
padding: 8px;
background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;
opacity: .3;
filter: Alpha(Opacity=30);
border-radius: 8px;
}

File diff suppressed because one or more lines are too long

8
dist/torque.full.js vendored

File diff suppressed because one or more lines are too long

39945
dist/torque.full.uncompressed.js vendored Normal file

File diff suppressed because it is too large Load Diff

4
dist/torque.js vendored

File diff suppressed because one or more lines are too long

BIN
dist/torque.js.gz vendored

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,104 +0,0 @@
# Torque API
## L.TorqueLayer(options)
One of two core classes for the Torque library - it is used to create an animated torque layer with custom settings.
### Usage example
```js
// initialize a torque layer that uses the CartoDB account details and SQL API to pull in data
var torqueLayer = new L.TorqueLayer({
user : 'viz2',
table : 'ow',
cartocss: CARTOCSS
});
```
### Options
##### Provider options
| Option | type | Default | Description |
|-----------|:-----------|:----------|:---------------------------------------|
| provider | string | ```sql_api``` | Where is the data coming from |
##### 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 |
| sql | string | ```null``` | SQL query to be performed to fetch the data. You must use this param or table, not at the same time |
### 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)
| ```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
| Method | options | returns | Description |
|-----------|:-----------|:----------|:---------------------------------------|
| ```setCartoCSS(cartocss)``` | ```cartocss string``` | ```this``` | style the map rendering using client-side cartocss |
The full CartoCSS spec is not supported by Torque but instead only a limited subset with some additions related to torque rendering. To see the full list of supported parameters, read the [Torque CartoCSS documentation here](CartoCSS.md). ``value`` and ``zoom`` variables can be used. ``value`` is the value of aggregation (see ``countby`` constructor option). ``zoom`` is the current zoom being rendered
TorqueLayer currently expects ```marker``` styling
##### CartoCSS Example
This should be ```string``` encoded in Javascript
```css
#layer {,
marker-fill: #662506;
marker-width: 20;
[value > 1] { marker-fill: #FEE391; }
[value > 2] { marker-fill: #FEC44F; }
[value > 3] { marker-fill: #FE9929; }
[value > 4] { marker-fill: #EC7014; }
[value > 5] { marker-fill: #CC4C02; }
[value > 6] { marker-fill: #993404; }
[value > 7] { marker-fill: #662506; }
[frame-offset = 1] { marker-width: 20; marker-fill-opacity: 0.05;}', // renders the previos frame
[frame-offset = 2] { marker-fill: red; marker-width: 30; marker-fill-opacity: 0.02;}', // renders two frames ago from the current being rendered
}
```
### Interaction methods (only available for Leaflet)
| Method | options | returns | Description |
|-----------|:-----------|:----------|:---------------------------------------|
| ```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``
| ```invalidate()```| | | forces a reload of the layer data.
# Google Maps Layers
## GMapsTorqueLayer(options)
This class does exactly the same than ``L.TorqueLayer`` but using Google Maps. The main difference is that this class
is not a layer is a overlay so in order to add it to the map use ``layer.setMap`` instead of ``overlayMapTypes``. See [Overlay view](https://developers.google.com/maps/documentation/javascript/reference#OverlayView) reference in Google Maps API doc.
### Options
##### options
| Option | type | Default | Description |
|-----------|:-----------|:----------|:---------------------------------------|
| map | google.maps.Map | | google.maps.Map instance |
see ``L.TorqueLayer`` for the rest of the options.

View File

@ -1,6 +1,6 @@
<html> <html>
<link rel="stylesheet" href="vendor/leaflet.css" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.css" />
<style> <style>
#map, html, body { #map, html, body {
width: 100%; height: 100%; padding: 0; margin: 0; width: 100%; height: 100%; padding: 0; margin: 0;
@ -9,9 +9,8 @@
<body> <body>
<div id="map"></div> <div id="map"></div>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false"></script> <script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script src="vendor/carto.js"></script> <script src="https://libs.cartocdn.com/torque.js/2.16.5/torque.full.js"></script>
<script src="../dist/torque.uncompressed.js"></script>
<script> <script>
@ -56,7 +55,8 @@
steps: 1024, steps: 1024,
blendmode : 'lighter', blendmode : 'lighter',
animationDuration: 20, animationDuration: 20,
map: map map: map,
tiler_protocol: 'https'
}); });
var DEFAULT_CARTOCSS = [ var DEFAULT_CARTOCSS = [

View File

@ -0,0 +1,99 @@
<html>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.css" />
<style>
#map, html, body {
width: 100%; height: 100%; padding: 0; margin: 0;
}
</style>
<body>
<div id="map"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.js"></script>
<script src="https://libs.cartocdn.com/torque.js/2.16.5/torque.full.js"></script>
<script>
// define the torque layer style using cartocss
var CARTOCSS = [
'Map {',
'-torque-time-attribute: "cartodb_id";',
'-torque-aggregation-function: "count(cartodb_id)";',
'-torque-frame-count: 1;',
'-torque-animation-duration: 15;',
'-torque-resolution: 2',
'}',
'#layer {',
'image-filters: colorize-alpha(blue, cyan, lightgreen, yellow , orange, red);',
'marker-file: url(https://s3.amazonaws.com/com.cartodb.assets.static/alphamarker.png);',
'marker-fill-opacity: 0.4;',
'marker-width: 35;',
'}'
].join('\n');
var map = new L.Map('map', {
zoomControl: true,
center: [40, 0],
zoom: 3
});
L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', {
attribution: 'CartoDB'
}).addTo(map);
var torqueLayer = new L.TorqueLayer({
user : 'fdansv',
table : 'snow',
cartocss: CARTOCSS,
tiler_protocol: 'https',
tiler_port: 443,
zIndex: 10
});
torqueLayer.addTo(map);
torqueLayer.play();
torqueLayer.bringToFront();
var rect = document.createElement("div");
var size = 50;
rect.setAttribute('style', "position:absolute; background-color: #fff; width: 100px; height: 30px;");
document.getElementById("map").appendChild(rect);
var curBounds = [];
var curRect;
var lastX =0, lastY=0;
var calc = function(e){
var x = e.clientX || lastX;
var y = e.clientY || lastY;
lastX = x;
lastY = y;
rect.style.display = "block";
rect.style.left = x + 20;
rect.style.top = y - 20;
rect.style.padding = 10;
var val = torqueLayer.getValueForBBox(x-size/2, y-size/2, size, size);
rect.textContent = val;
var nw = map.containerPointToLatLng([x-size/2, y-size/2]);
var se = map.containerPointToLatLng([x+size/2, y+size/2]);
curBounds = [[nw.lat, nw.lng], [se.lat, se.lng]];
if(curRect){
map.removeLayer(curRect);
}
curRect = L.rectangle(curBounds, {color: "#ff7800", weight: 1}).addTo(map);
};
document.onmousemove = calc;
document.onmouseout = function(e){
if (e.toElement == null && e.relatedTarget == null) {
rect.style.display = "none";
}
};
document.onkeypress = function(e){
if(e.keyCode === 97){
size +=4;
}
if(e.keyCode === 115){
size -=4;
}
calc(e);
}
</script>
</body>
</html>

View File

@ -0,0 +1,134 @@
<!DOCTYPE html>
<html>
<head>
<title>Heat map simple | CartoDB.js</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<link rel="shortcut icon" href="https://cartodb.com/assets/favicon.ico" />
<style>
html, body, #map {
height: 100%;
padding: 0;
margin: 0;
}
</style>
<link rel="stylesheet" href="https://libs.cartocdn.com/cartodb.js/v3/themes/css/cartodb.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/themes/css/cartodb.ie.css" />
<![endif]-->
<script type="sql/html" id="cartocss_template">
/** torque_cat visualization */
Map {
-torque-frame-count:64;
-torque-animation-duration:30;
-torque-time-attribute:"posttime";
-torque-aggregation-function:"sum(1)+CDB_Math_Mode(direction)*100";
-torque-resolution:2;
-torque-data-aggregation:linear;
}
#cleveland_spring_points{
comp-op: source-over;
marker-fill-opacity: 1;
marker-line-color: #FFF;
marker-line-width: 0;
marker-line-opacity: 1;
marker-type: ellipse;
marker-width: 1;
marker-fill: #F84F40;
}
#cleveland_spring_points[value>101] {
marker-width:2;
}
#cleveland_spring_points[value>102] {
marker-width:3;
}
#cleveland_spring_points[value>103] {
marker-width:5;
}
#cleveland_spring_points[value>104] {
marker-width:8;
}
#cleveland_spring_points[value>105] {
marker-width:12;
}
#cleveland_spring_points[value>106] {
marker-width:15;
}
#cleveland_spring_points[value>200] {
marker-fill: #5CA2D1;
marker-width:1;
}
#cleveland_spring_points[value>201] {
marker-width:2;
}
#cleveland_spring_points[value>202] {
marker-width:3;
}
#cleveland_spring_points[value>203] {
marker-width:5;
}
#cleveland_spring_points[value>204] {
marker-width:8;
}
#cleveland_spring_points[value>205] {
marker-width:12;
}
#cleveland_spring_points[value>206] {
marker-width:15;
}
#cleveland_spring_points[frame-offset=1] {
marker-width:2;
marker-fill-opacity:0.45;
}
#cleveland_spring_points[frame-offset=2] {
marker-width:4;
marker-fill-opacity:0.225;
}
</script>
</head>
<body>
<div id="map"></div>
<!-- include cartodb.js library -->
<script src="https://libs.cartocdn.com/cartodb.js/v3/cartodb.js"></script>
<script>
function main() {
var map = new L.Map('map', {
zoomControl: false,
center: [40.72209113, -73.99824792],
zoom: 14
});
var layer = L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png',{
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://cartodb.com/attributions">CartoDB</a>'
}).addTo(map);
cartodb.createLayer(map, {
type: "torque",
order: 1,
options: {
query: "",
table_name: "cleveland_spring_points",
user_name: "andrew",
tile_style: $('#cartocss_template').html()
}
}, {
https: true,
tiler_protocol: 'https',
tiler_port: 443
}).done(function(layer) {
map.addLayer(layer);
});
}
// you could use $(window).load(main);
window.onload = main;
</script>
</body>
</html>

View File

@ -0,0 +1,57 @@
{
"main": {
"file": "static_bubble_map.html"
},
"categories": [
{
"title": "Static",
"samples": [
{
"title": "Bubble Map",
"desc": "",
"file": "static_bubble_map.html"
},
{
"title": "Heatmap",
"desc": "",
"file": "static_heat_map.html"
},
{
"title": "Heatmap Simple",
"desc": "",
"file": "static_heat_map_simple.html"
}
]
},
{
"title": "Misc",
"samples": [
{
"title": "Light Bright",
"desc": "",
"file": "light_bright.html"
},
{
"title": "Dual Encode",
"desc": "",
"file": "dual_encode.html"
},
{
"title": "Navy Ships GMaps",
"desc": "",
"file": "navy_gmaps.html"
},
{
"title": "Navy Ships Leaflet",
"desc": "",
"file": "navy_leaflet.html"
},
{
"title": "Navy Ships OpenLayers",
"desc": "",
"file": "navy_ol.html"
}
]
}
]
}

View File

@ -1,6 +1,5 @@
<html> <html>
<link rel="stylesheet" href="vendor/leaflet.css" />
<style> <style>
#map, html, body { #map, html, body {
width: 100%; height: 100%; padding: 0; margin: 0; width: 100%; height: 100%; padding: 0; margin: 0;
@ -18,9 +17,9 @@
<div id="map"></div> <div id="map"></div>
<div id="title">Average temperature collected by Britain's Royal Navy (1913-1925)</div> <div id="title">Average temperature collected by Britain's Royal Navy (1913-1925)</div>
<script src="vendor/leaflet.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.css" />
<script src="vendor/carto.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.js"></script>
<script src="../dist/torque.uncompressed.js"></script> <script src="../dist/torque.full.uncompressed.js"></script>
<script> <script>
@ -57,14 +56,17 @@
zoom: 3 zoom: 3
}); });
L.tileLayer('http://{s}.api.cartocdn.com/base-dark/{z}/{x}/{y}.png', { L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', {
attribution: 'CartoDB' attribution: 'CartoDB'
}).addTo(map); }).addTo(map, true);
var torqueLayer = new L.TorqueLayer({ var torqueLayer = new L.TorqueLayer({
user : 'viz2', user : 'viz2',
table : 'ow', table : 'ow',
cartocss: CARTOCSS cartocss: CARTOCSS,
tiler_protocol: 'https',
tiler_port: 443,
zIndex: 10
}); });
torqueLayer.addTo(map); torqueLayer.addTo(map);

View File

@ -0,0 +1,97 @@
<!DOCTYPE html>
<html>
<head>
<title>Light bright effect | CartoDB.js</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<link rel="shortcut icon" href="https://cartodb.com/assets/favicon.ico" />
<style>
html, body, #map {
height: 100%;
padding: 0;
margin: 0;
}
</style>
<link rel="stylesheet" href="https://libs.cartocdn.com/cartodb.js/v3/themes/css/cartodb.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/themes/css/cartodb.ie.css" />
<![endif]-->
<script type="sql/html" id="cartocss_template">
Map {
-torque-frame-count:32;
-torque-animation-duration:14;
-torque-time-attribute:"postedtime";
-torque-aggregation-function:"count(cartodb_id)";
-torque-resolution:16;
-torque-data-aggregation:linear;
}
#twitter_wowfakta{
comp-op: lighter;
marker-fill-opacity: 0.9;
marker-line-color: #FFF;
marker-line-width: 0;
marker-line-opacity: 1;
marker-type: ellipse;
marker-width: 1;
marker-fill: #F84F40;
}
#twitter_wowfakta[value>1] {
marker-width:2;
}
#twitter_wowfakta[value>2] {
marker-width:3;
}
#twitter_wowfakta[value>4] {
marker-width:5;
}
#twitter_wowfakta[value>8] {
marker-width:7;
}
#twitter_wowfakta[value>16] {
marker-width:9;
}
#twitter_wowfakta[value>32] {
marker-width:8;
}
</script>
</head>
<body>
<div id="map"></div>
<!-- include cartodb.js library -->
<script src="https://libs.cartocdn.com/cartodb.js/v3/cartodb.js"></script>
<script>
function main() {
var map = new L.Map('map', {
zoomControl: false,
center: [-6.964483, 107.634506],
zoom: 7
});
var layer = L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png',{
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://cartodb.com/attributions">CartoDB</a>'
}).addTo(map);
cartodb.createLayer(map, {
type: "torque",
order: 1,
options: {
table_name: "twitter_wowfakta",
user_name: "andrew",
tile_style: $('#cartocss_template').html()
}
}, {
https: true,
tiler_protocol: 'https',
tiler_port: 443
}).done(function(layer) {
map.addLayer(layer);
});
}
// you could use $(window).load(main);
window.onload = main;
</script>
</body>
</html>

View File

@ -8,9 +8,8 @@
<div id="map"></div> <div id="map"></div>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false"></script> <script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script src="vendor/carto.js"></script> <script src="https://libs.cartocdn.com/torque.js/2.16.5/torque.full.js" type="application/javascript" charset="utf-8"></script>
<script src="../dist/torque.uncompressed.js"></script>
<script> <script>
@ -76,9 +75,14 @@
user : 'viz2', user : 'viz2',
table : 'ow', table : 'ow',
cartocss: CARTOCSS, cartocss: CARTOCSS,
map: map tiler_protocol: 'https',
tiler_port: 443
});
torqueLayer.error(function(err){
for(error in err){
console.warn(err[error]);
}
}); });
torqueLayer.setMap(map); torqueLayer.setMap(map);
torqueLayer.play() torqueLayer.play()
} }

View File

@ -0,0 +1,70 @@
<html>
<style>
#map, html, body {
width: 100%; height: 100%; padding: 0; margin: 0;
}
</style>
<body>
<div id="map"></div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.js"></script>
<script src="https://libs.cartocdn.com/torque.js/2.16.5/torque.full.js" type="application/javascript" charset="utf-8"></script>
<script>
// define the torque layer style using cartocss
var CARTOCSS = [
'Map {',
'-torque-time-attribute: "date";',
'-torque-aggregation-function: "count(cartodb_id)";',
'-torque-frame-count: 760;',
'-torque-animation-duration: 15;',
'-torque-resolution: 2',
'}',
'#layer {',
' marker-width: 3;',
' marker-fill-opacity: 0.8;',
' marker-fill: #FEE391; ',
' comp-op: "lighten";',
' [value > 2] { marker-fill: #FEC44F; }',
' [value > 3] { marker-fill: #FE9929; }',
' [value > 4] { marker-fill: #EC7014; }',
' [value > 5] { marker-fill: #CC4C02; }',
' [value > 6] { marker-fill: #993404; }',
' [value > 7] { marker-fill: #662506; }',
' [frame-offset = 1] { marker-width: 10; marker-fill-opacity: 0.05;}',
' [frame-offset = 2] { marker-width: 15; marker-fill-opacity: 0.02;}',
'}'
].join('\n');
var map = new L.Map('map', {
zoomControl: true,
center: [40, 0],
zoom: 3
});
L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', {
attribution: 'CartoDB'
}).addTo(map);
var torqueLayer = new L.TorqueLayer({
user : 'viz2',
table : 'ow',
zIndex: 100,
cartocss: CARTOCSS,
tiler_protocol: 'https',
tiler_port: 443
});
torqueLayer.error(function(err){
for(error in err){
console.warn(err[error]);
}
});
torqueLayer.addTo(map);
torqueLayer.play()
</script>
</body>
</html>

View File

@ -0,0 +1,75 @@
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>CartoDb Torque Layer Example</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.17.1/ol.css" type="text/css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.17.1/ol.js"></script>
<style>
#map, html, body {
width: 100%; height: 100%; padding: 0; margin: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="https://libs.cartocdn.com/torque.js/2.16.5/torque.full.js" type="application/javascript" charset="utf-8"></script>
<script>
// define the torque layer style using cartocss
var CARTOCSS = [
'Map {',
'-torque-time-attribute: "date";',
'-torque-aggregation-function: "count(cartodb_id)";',
'-torque-frame-count: 760;',
'-torque-animation-duration: 15;',
'-torque-resolution: 2',
'}',
'#layer {',
' marker-width: 3;',
' marker-fill-opacity: 0.8;',
' marker-fill: #FEE391; ',
' comp-op: "lighten";',
' [value > 2] { marker-fill: #FEC44F; }',
' [value > 3] { marker-fill: #FE9929; }',
' [value > 4] { marker-fill: #EC7014; }',
' [value > 5] { marker-fill: #CC4C02; }',
' [value > 6] { marker-fill: #993404; }',
' [value > 7] { marker-fill: #662506; }',
' [frame-offset = 1] { marker-width: 10; marker-fill-opacity: 0.05;}',
' [frame-offset = 2] { marker-width: 15; marker-fill-opacity: 0.02;}',
'}'
].join('\n');
var map = new ol.Map({
target: "map",
view: new ol.View({
center: [40, 0],
zoom: 3
}),
layers: [
new ol.layer.Tile({
source: new ol.source.XYZ({ url: 'https://basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png'})
})
],
interactions: ol.interaction.defaults({
dragPan: false
}).extend([
new ol.interaction.DragPan({kinetic: false})
])
});
var torqueLayer = new ol.TorqueLayer({
user : 'viz2',
table : 'ow',
cartocss: CARTOCSS,
tiler_protocol: 'https',
tiler_port: 443
});
torqueLayer.onAdd(map);
torqueLayer.play()
</script>
</body>
</html>

View File

@ -0,0 +1,83 @@
<html>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.css" />
<style>
#map, html, body {
width: 100%; height: 100%; padding: 0; margin: 0;
}
#range-control {
text-align: right;
padding: 4px 0;
}
</style>
<body>
<div id="range-control">
Render range:
<label for="start">start</label> <input id="start" value="90">
<label for="end">end</label> <input id="end" value="180">
<button onclick="renderRange()">Apply</button>
<button onclick="resetRenderRange()">Reset</button>
</div>
<div id="map"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.js"></script>
<script src="https://libs.cartocdn.com/torque.js/2.16.5/torque.full.js"></script>
<script>
// define the torque layer style using cartocss
var CARTOCSS = [
'Map {',
' -torque-frame-count: 360;',
' -torque-animation-duration: 30;',
' -torque-time-attribute: "cartodb_id";',
' -torque-aggregation-function: "count(cartodb_id)";',
' -torque-resolution: 1;',
' -torque-data-aggregation: linear;',
'}',
'#generate_series {',
' comp-op: lighter;',
' marker-fill-opacity: 0.9;',
' marker-line-color: #FFF;',
' marker-line-width: 0;',
' marker-line-opacity: 1;',
' marker-type: rectable;',
' marker-width: 6;',
' marker-fill: #0F3B82;',
'}'
].join('\n');
var map = new L.Map('map', {
zoomControl: true,
center: [0, 0],
zoom: 2
});
L.tileLayer('http://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://cartodb.com/attributions">CartoDB</a>'
}).addTo(map);
var torqueLayer = new L.TorqueLayer({
user: 'documentation',
sql: 'SELECT s + 181 as cartodb_id, st_transform(ST_SetSRID (st_makepoint(s, 10*sin(s)), 4326), 3857) as the_geom_webmercator FROM generate_series(-180, 180, 1) as s',
cartocss: CARTOCSS,
tiler_protocol: 'https',
tiler_port: 443,
zIndex: 10
});
torqueLayer.error(console.warn);
torqueLayer.addTo(map);
torqueLayer.play();
function renderRange() {
var start = document.getElementById('start').value;
var end = document.getElementById('end').value;
torqueLayer.renderRange(+start, +end);
}
function resetRenderRange() {
torqueLayer.resetRenderRange();
}
</script>
</body>
</html>

View File

@ -0,0 +1,94 @@
<!DOCTYPE html>
<html>
<head>
<title>Static bubble map | CartoDB.js</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<link rel="shortcut icon" href="https://cartodb.com/assets/favicon.ico" />
<style>
html, body, #map {
height: 100%;
padding: 0;
margin: 0;
}
</style>
<link rel="stylesheet" href="https://libs.cartocdn.com/cartodb.js/v3/themes/css/cartodb.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/themes/css/cartodb.ie.css" />
<![endif]-->
<script type="sql/html" id="cartocss_template">
Map {
-torque-frame-count:0.5;
-torque-animation-duration:0;
-torque-time-attribute:"cartodb_id";
-torque-aggregation-function:"max(no2)";
-torque-resolution:2;
-torque-data-aggregation:cumulative;
}
#aqi{
comp-op: lighter;
marker-fill-opacity: 0.9;
marker-line-color: #FFF;
marker-line-width: 1.5;
marker-line-opacity: 1;
marker-type: ellipse;
marker-width: 30;
marker-fill: #F84F40;
[value < 50]{
marker-width: 24;
[value < 40]{
marker-width: 18;
[value < 30]{
marker-width: 12;
[value < 20]{
marker-width: 6;
[value < 10]{
marker-width: 3;
}
}
}
}
}
}
</script>
</head>
<body>
<div id="map"></div>
<!-- include cartodb.js library -->
<script src="https://libs.cartocdn.com/cartodb.js/v3/cartodb.uncompressed.js"></script>
<script>
function main() {
var map = new L.Map('map', {
zoomControl: false,
center: [39.9304, 116.423239],
zoom: 8
});
var layer = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',{
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://cartodb.com/attributions">CartoDB</a>'
}).addTo(map);
cartodb.createLayer(map, {
type: "torque",
order: 1,
options: {
table_name: "harvard_aqi",
user_name: "andrew",
tile_style: $('#cartocss_template').html()
}
}, {
https: true,
tiler_protocol: 'https',
tiler_port: 443
}).done(function(layer) {
map.addLayer(layer);
});
}
// you could use $(window).load(main);
window.onload = main;
</script>
</body>
</html>

View File

@ -0,0 +1,93 @@
<!DOCTYPE html>
<html>
<head>
<title>Torque heatmap | CartoDB.js</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<link rel="shortcut icon" href="https://cartodb.com/assets/favicon.ico" />
<style>
html, body, #map {
height: 100%;
padding: 0;
margin: 0;
}
</style>
<link rel="stylesheet" href="https://libs.cartocdn.com/cartodb.js/v3/themes/css/cartodb.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/themes/css/cartodb.ie.css" />
<![endif]-->
<script type="sql/html" id="cartocss_template">
Map {
-torque-frame-count:0.5;
-torque-animation-duration:0;
-torque-time-attribute:"cartodb_id";
-torque-aggregation-function:"count(cartodb_id)";
-torque-resolution:2;
-torque-data-aggregation:cumulative;
}
#monkey_jump{
// comp-op: lighter;
marker-opacity: 0.9;
marker-line-color: #FFF;
marker-line-width: 0;
marker-line-opacity: 1;
marker-type: arrow;
marker-width: 2;
marker-fill: #B10026;
[value < 12]{
marker-fill:#FC4E2A;
[value < 4]{
marker-fill:#FD8D3C;
[value < 3]{
marker-fill:#FEB24C;
[value < 2]{
marker-fill:#FFFFB2;
}
}
}
}
}
</script>
</head>
<body>
<div id="map"></div>
<!-- include cartodb.js library -->
<script src="https://libs.cartocdn.com/cartodb.js/v3/cartodb.js"></script>
<script>
function main() {
var map = new L.Map('map', {
zoomControl: false,
center: [-6.514293, 110],
zoom: 7
});
var layer = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',{
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://cartodb.com/attributions">CartoDB</a>'
}).addTo(map);
cartodb.createLayer(map, {
type: "torque",
order: 1,
options: {
query: "",
table_name: "twitter_wowfakta",
user_name: "andrew",
tile_style: $('#cartocss_template').html()
}
}, {
https: true,
tiler_protocol: 'https',
tiler_port: 443
}).done(function(layer) {
map.addLayer(layer);
});
}
// you could use $(window).load(main);
window.onload = main;
</script>
</body>
</html>

View File

@ -0,0 +1,80 @@
<!DOCTYPE html>
<html>
<head>
<title>Heat map simple | CartoDB.js</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<link rel="shortcut icon" href="https://cartodb.com/assets/favicon.ico" />
<style>
html, body, #map {
height: 100%;
padding: 0;
margin: 0;
}
</style>
<link rel="stylesheet" href="https://libs.cartocdn.com/cartodb.js/v3/themes/css/cartodb.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="http://libs.cartocdn.com/cartodb.js/v3/themes/css/cartodb.ie.css" />
<![endif]-->
<script type="sql/html" id="cartocss_template">
Map {
-torque-frame-count:0.5;
-torque-animation-duration:0;
-torque-time-attribute:"cartodb_id";
-torque-aggregation-function:"count(cartodb_id)";
-torque-resolution:2;
-torque-data-aggregation:cumulative;
}
#monkey_jump{
comp-op: lighter;
marker-opacity: 0.9;
marker-line-color: #FFF;
marker-line-width: 0;
marker-line-opacity: 1;
marker-type: ellipse;
marker-width: 4;
marker-fill: #FF2900;
}
</script>
</head>
<body>
<div id="map"></div>
<!-- include cartodb.js library -->
<script src="https://libs.cartocdn.com/cartodb.js/v3/cartodb.js"></script>
<script>
function main() {
var map = new L.Map('map', {
zoomControl: false,
center: [-6.514293, 110],
zoom: 7
});
var layer = L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',{
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="http://cartodb.com/attributions">CartoDB</a>'
}).addTo(map);
cartodb.createLayer(map, {
type: "torque",
order: 1,
options: {
query: "",
table_name: "twitter_wowfakta",
user_name: "andrew",
tile_style: $('#cartocss_template').html()
}
}, {
https: true,
tiler_protocol: 'https',
tiler_port: 443
}).done(function(layer) {
map.addLayer(layer);
});
}
// you could use $(window).load(main);
window.onload = main;
</script>
</body>
</html>

View File

@ -1,5 +1,5 @@
<html> <html>
<link rel="stylesheet" href="vendor/leaflet.css" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.css" />
<style> <style>
#map, html, body { #map, html, body {
width: 100%; height: 100%; padding: 0; margin: 0; width: 100%; height: 100%; padding: 0; margin: 0;
@ -8,9 +8,8 @@
<body> <body>
<div id="map"></div> <div id="map"></div>
<script src="vendor/leaflet.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.js"></script>
<script src="vendor/carto.js"></script> <script src="../dist/torque.full.uncompressed.js"></script>
<script src="../dist/torque.uncompressed.js"></script>
<script> <script>
@ -51,10 +50,14 @@
}).addTo(map); }).addTo(map);
var torqueLayer = new L.TorqueLayer({ var torqueLayer = new L.TorqueLayer({
user : 'viz2', tileJSON: "http://localhost:4000/examples/tilejson.json",
table : 'ow',
cartocss: CARTOCSS cartocss: CARTOCSS
}); });
torqueLayer.error(function(err){
for(error in err){
console.warn(err[error]);
}
});
torqueLayer.addTo(map); torqueLayer.addTo(map);
torqueLayer.play() torqueLayer.play()
</script> </script>

View File

@ -0,0 +1,8 @@
{
"start": -1796072400000,
"end": -1414843200000,
"resolution": 2,
"data_steps": 861786,
"column_type": "date",
"tiles": ["http://{s}.ashbu.cartocdn.com/viz2/api/v1/map/cf28c540d3cf15a29a759f84ff440679:0/0/{z}/{x}/{y}.json.torque"]
}

View File

@ -0,0 +1,77 @@
## Getting Started
Although the most straightforward way to use Torque is through either CARTO Builder, or by passing the layer's viz.json to [CARTO.js]({{site.cartojs_docs}}/), many use cases work best with the standalone Torque.js. Assuming you have a public dataset with a `date` column, it is really simple to create an animated map with the library. First, you need to have a Leaflet map prepared in an HTML page:
```html
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css" />
<body>
<div id="map"></div>
<script src="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js"></script>
<script>
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: 'CARTO'
}).addTo(map);
</script>
</body>
```
This HTML file automatically generates the Torque.js library, which includes any Torque dependencies. For Torque to work with your table, you only need a username, the name of the table, and a [CartoCSS]({{site.styling_cartocss}}/) string to style the map. Leaflet's method `addTo` adds the Torque layer to the map. `play` runs the animation with the options specified in the CartoCSS properties.
```html
<script>
var CARTOCSS = [
'Map {',
'-torque-time-attribute: "date";',
'-torque-aggregation-function: "count(cartodb_id)";',
'-torque-frame-count: 760;',
'-torque-animation-duration: 15;',
'-torque-resolution: 2',
'}',
'#layer {',
' marker-width: 3;',
' marker-fill-opacity: 0.8;',
' marker-fill: #FEE391; ',
' comp-op: "lighten";',
'}'
].join('\n');
var torqueLayer = new L.TorqueLayer({
user : 'your_username',
table : 'your_table_name',
cartocss: CARTOCSS
});
torqueLayer.addTo(map);
torqueLayer.play()
</script>
```
You can use any kind of tile source outside CARTO, by specifying the location of a [valid TileJSON](https://github.com/mapbox/tilejson-spec) file:
```javascript
var torqueLayer = new L.TorqueLayer({
tileJSON: 'http://url.to/tile.json'
cartocss: CARTOCSS
});
```
Optionally, it is also possible to use a custom SQL query for your visualization:
```javascript
var torqueLayer = new L.TorqueLayer({
user : 'your_username',
table : 'your_table_name',
sql_query : 'SELECT * FROM your_table_name WHERE whatever'
cartocss: CARTOCSS
});
```
Like in a video player, you can use animation control methods such as `play`, `stop` and `pause` at any point. Torque's animator fires a `change:time` event each time the animation "ticks" to the next frame, and there are a number of properties and methods that can be run during playback, which are detailed in the [API reference]({{site.torque_docs}}/reference/). At any point, for example, the styling of the layer's markers can be changed using the `layer.setCartoCSS('##style##')`.
### Usage Examples
The best way to start learning about the library is by taking a look at the [examples section]({{site.torque_docs}}/examples/).

View File

@ -0,0 +1,24 @@
## Torque CartoCSS
CartoCSS is one the tools of the CARTO platform. You can learn more about the different [components of CARTO platform]({{site.fundamental_docs}}/components/), or directly dig into [CartoCSS too]({{site.styling_cartocss}}/) details.
`-torque-clear-color`
Color used to clear canvas on each frame.
`-torque-frame-count`
Number of animation steps/frames used in the animation. If the data contains a fewer number of total frames, the lesser value will be used.
`-torque-resolution`
Spatial resolution in pixels. A resolution of 1 means no spatial aggregation of the data. Any other resolution of N results in spatial aggregation into cells of NxN pixels. The value N must be power of 2.
`-torque-animation-duration`
Animation duration in seconds.
`-torque-aggregation-function`
A function used to calculate a value from the aggregate data for each cell. See [-torque-resolution](#-torque-resolution).
`-torque-time-attribute`
The table column that contains the time information used create the animation.
`-torque-data-aggregation`
A linear animation will discard previous values while a cumulative animation will accumulate them until it restarts.

View File

@ -0,0 +1,138 @@
## Advanced Torque.js Interaction Methods
### Torque Layers
While you can add multiple layers with Torque.js, this is not recommended as it effects performance.
#### Torque Layer Source Object (_type: 'torque'_)
This layer source object is used for Torque maps. Note that it does not allow sublayers.
##### Example
```javascript
{
type: 'torque', // Required
order: 1, // Optional
options: {
query: "SQL statement", // Required if table_name is not given
table_name: "table_name", // Required if query is not given
user_name: "your_user_name", // Required
cartocss: "CartoCSS styles" // Required
}
}
```
### Interaction Methods for a Torque Layer
Used to create an animated torque layer with customized settings.
```javascript
// initialize a torque layer that uses the CARTO account details and SQL API to pull in data
var torqueLayer = new L.TorqueLayer({
user : 'viz2',
table : 'ow',
cartocss: CARTOCSS
});
```
#### getValueForPos(_x, y[, step]_)
##### Arguments
Name | Description
--- | ---
`getValueForPos(_x, y[, step]_)` | Allows to get the value for the coordinate (in map reference system) for a concrete step. If a step is not specified, the animation step is used. Use caution, as this method increases CPU usage
##### Returns
An object, such as a { bbox:[], value: VALUE } if there is value for the pos, otherwise, it is null.
It returns the value from the raster data, not the rendered data.
#### getValueForBBox(_xstart, ystart, xend, yend_)
##### Arguments
Name | Description
--- | ---
`getValueForBBox(_xstart, ystart, xend, yend_)` | An accumulated numerical value from all the torque areas, within the specified bounds
##### Returns
Returns a number.
#### getActivePointsBBox(_step_)
##### Arguments
Name | Description
--- | ---
`getActivePointsBBox(_step_)` | The list of bounding boxes active for `step`
##### Returns
Returns a list of values.
#### invalidate()
##### Arguments
Name | Description
--- | ---
`invalidate()` | Forces a reload of the layer data
**Tip:** All of these interaction methods are available for Google Map layers, with the exception of `invalidate`.
##### Example of Interaction Methods for a Torque Layer
```javascript
<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: 'CARTO'
}).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);
}
});
```

View File

@ -0,0 +1,60 @@
## Torque Time Slider
You can use the `time_slider` option to show an animated time slider with Torque layers. This option is enabled by default when creating visualizations with [cartodb.createVis]({{site.cartojs_docs}}/v3/reference/#cartodbcreatevis) and [createLayer]({{site.cartojs_docs}}/v3/reference/#cartodbcreatelayermap-layersource--options--callback). Both require a map_id DOM object.
**Enable / Disable the Torque Time Slider**
Description | The Torque time slider is enabled by default, for your visualization or layer.
Sample Torque.js Code | `{ time_slider: true });`
Default Value | `true`, enabled by default.
Available Values | See [boolean]({{site.styling_cartocss}}/#boolean).
Related Examples | To disable the time slider option, use `time_slider: false`. See [No Torque Time Slider - Example Code](http://bl.ocks.org/michellechandra/081ca7160a8c782266d2).<br/><br/>For a code example about how to use the `time_slider` option to modify a Torque map, see [Torque with a Custom Time Slider](http://bl.ocks.org/csobier/cebdd47242d7ca98ec5e).
**Note:** The `time_slider` option is specific for Torque.js only. All the other CARTO.js options are also supported for Torque.js. For the complete list of arguments, options, and returns, see [CARTO.js API Methods]({{site.cartojs_docs}}/v3/reference/#api-methods).
### Customize Animation for your Time Slider
You can customize the animation of your Torque time slider by editing the `-torque-frame-count` and `-torque-animation-duration` CartoCSS properties. (Optionally, you can create a [CARTO.js]({{site.cartojs_docs}}/v3/reference/#api-methods) map to create a custom time slider). This section also describes how time interval data is aggregated, and describes the formula used to calculate time buckets.
- [`-torque-frame-count`]({{site.styling_cartocss}}/#-torque-frame-count-number) specifies the number of animation steps/frames in your torque animation. You can change the time slider timestamp by adjusting the number of steps.<br /><br />**Tip:** In CARTO Builder, this is the STEPS value when the style is ANIMATED.
- [`-torque-animation-duration`]({{site.styling_cartocss}}/#-torque-animation-duration-number) specifies the length of time for your animation, in seconds. You can adjust the duration of the animation as needed.<br /><br />**Tip:** In CARTO Builder, this is the DURATION value when the style is ANIMATED.
#### Aggregating Time Interval Data
Before customizing the time slider, you should understand how Torque time interval data is calculated. Torque aggregates time (rather than use an exact start time and end from your column fields). Torque calculates the time interval as follows:
- Reads the first date/time stamp from your dataset
- Reads the last date/time stamp to from your dataset
- Aggregates the time period based on the first and last date/time stamp (including seconds)
- Once the time interval is defined, it breaks the time period up in smaller "buckets"
- The number of buckets is based on the number of [Steps]({{site.styling_cartocss}}/#-torque-frame-count-number) you select for your Torque map
- Each bucket, or step, is one animation frame
Thus, the start and end time for each bucket depends on the number of divided steps (not a specific start time or end time that you entered).
**Note:** If you are creating Torque maps with CARTO Builder, the date format of the Torque time slider is automatically calculated by CARTO and cannot be edited. See [Calculating the Time Slider in CARTO Builder](#calculating-the-time-slider-in-carto-builder) for more details.
#### Formula for Calculating Time Buckets
The following formula can help you calculate the number of steps for your Torque data.
`time = times.start + (times.end - times.start)*(step/total_steps);`
Where:
- `time` = time at each hop
- `times.start` = the earliest time in your date/time column
- `times.end` = the latest time in your date/time column
The Torque time slider displays these buckets of time, animating the entire sequence of your dataset, and divides the time according to the number of specified steps. You can alter the [duration]({{site.styling_cartocss}}/#-torque-animation-duration-number) of the animation, and adjust the time slider timestamp with the number of [Steps]({{site.styling_cartocss}}/#-torque-frame-count-number).
##### Calculating the Time Slider in CARTO Builder
When creating Torque maps with CARTO Builder, the date format of the Torque time slider is automatically calculated by CARTO, depending on the range of time in your dataset. It cannot be edited. If your data contains the following range of time, the time slider displays as described:
- Time range is _less than one day_, the time slider displays the _time_
- Time range is _less than three days_, the time slider displays the _day and time_
- Time range is _more than three days, but less than a year_, the time slider displays the _month/day/year_
- Time range is _more than a year_, the time slider displays the _month/year_

View File

@ -0,0 +1,69 @@
## How spatial aggregation works
When the Torque library renders points, it does not render exactly the same points you have in the database; instead it aggregates the points in clusters in order to speed up rendering and data transfer.
So imagine you have this CartoCSS:
```css
Map {
-torque-aggregation-function:"count(cartodb_id)";
-torque-resolution: 2;
}
```
This means that for the current zoom level, Torque will fetch points in clusters of 2x2 pixels. Every cluster has a value calculated by the function defined after ``-torque-aggregation-function``. In the case above, the value will be the number of points inside that cluster. That value can be accessed from CartoCSS using the variable `value`.
Every cluster is renderer as a point.
Given that you can do:
```css
#layer {
[value > 1] { marker-fill: #000; }
[value > 4] { marker-fill: #400; }
[value > 16] { marker-fill: #800; }
[value > 32] { marker-fill: #F00; }
}
```
This would render the point with different colors depending on the number of points inside it.
## Can I use strings with Torque?
In general you can **not** do:
```css
[column = 'mytext'] { marker-fill: red; }
```
There are two reasons for this limitation:
- cluster does not contain values for all the columns, you can only use ``value`` variable
- you would need to use an aggregation function for strings
So how could I use strings column with Torque?
Imagine you have a string column (`team`) with two values, "team A" and "team B", and you want to color "team A" points to be red and "team B" to be blue, you could add a new column on the fly:
```javascript
torqueLayer.setSQL("select *, (CASE WHEN team='team A' THEN 1 ELSE 2 END) as team_n from table");
```
and then apply this CartoCSS:
```css
Map {
...
-torque-aggregation-function: "round(avg(team_n))";
...
}
#layer {
...
marker-fill: #FF0000;
// avg of 1 and 2
[value > 1.5] { marker-fill: #0000FF; }
...
}
```
**Tip:** CartoCSS is one the tools of the CARTO platform. You can learn more about the different [components of CARTO platform]({{site.fundamental_docs}}/components/), or directly dig into [CartoCSS]({{site.styling_cartocss}}/) details.

1
docs/img/image Normal file
View File

@ -0,0 +1 @@

View File

@ -0,0 +1,5 @@
## Introduction
Torque.js is an efficient and stylish rendering method to animate your data.
The contents described in this document are subject to CARTO's [Terms of Service](https://carto.com/legal/)

View File

@ -0,0 +1,3 @@
## Versioning
Torque.js uses [Semantic Versioning](http://semver.org/). View our Github repository to find tags for each [release](https://github.com/CartoDB/torque/releases).

View File

@ -0,0 +1,28 @@
## L.TorqueLayer
A layer to be added to a Leaflet map. It works as a regular tiled layer within the Leaflet tile pane, but instead of containing `<img>` elements, it's composed of a single [`<canvas>`](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) where all markers are drawn.
**Example:**
```javascript
var torqueLayer = new L.TorqueLayer({
user: 'viz2',
table: 'ow',
cartocss: '<cartocss here>'
});
map.addLayer(torqueLayer);
```
### Options
Name | Description
--- | ---
cartocss | A string object, the CartoCSS style for the map. Default value is ```null```
loop | A boolean object that defines the animation loop. Default value is ```true```. If ```false```, the animation is paused when it reaches the last frame
resolution | Spatial resolution in pixels. A resolution of 1 means no spatial aggregation of the data. Its value must be a power of 2
steps | Number of steps that the animation is divided into
animationDuration | Duration, in seconds, of the animation
zIndex | Z-Index CSS property of the layer
attribution | Attribution to be added in the bottom right of the map
maxZoom | Maximum zoom for the layer.
tileSize | Size, in pixels of the tiles

View File

@ -0,0 +1,6 @@
## Using a CARTO table directly
Name | Description
--- | ---
user | A string object, your CARTO [account name](https://carto.com/docs/carto-editor/your-account/#account). Default value is ```null```
table | A string object, the CARTO table name where data is found (also known as a dataset.) Default value is ```null```

View File

@ -0,0 +1,5 @@
## Using a custom SQL query
Name | Description
--- | ---
query | A string object, the SQL query to be performed to fetch the data. Default value is ```null```.<br/><br/>You must use this param or table, but not at the same time
**Tip:** For a Torque category layer that is created dynamically with `cartodb.createLayer`, the SQL query must explicitly include how to build the torque_category column. You must include both the `sql` and `table_name` parameters. See this [createLayer with torque category layer](https://gist.github.com/danicarrion/dcaf6f00a71aa55134b4) example.

View File

@ -0,0 +1,9 @@
## Providing a TileJSON file
Name | Description
--- | ---
tileJSON | A URL pointing to a valid [TileJSON](https://github.com/mapbox/tilejson-spec) file from which to get the Torque tile templates
Add Comment

View File

@ -0,0 +1,14 @@
## Time Methods
Method | Options | Returns | Description |
---|---|---|---|
`setStep(step)` | `time numeric` | `this` | the value must be between 0 and the total number of `steps` in the animation
`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. A step is considered an animation frame
`getTime()` | | current animation time (Date) | gets the real animation time
`isRunning()` | | `true`/`false` | describes whether the Torque layer is playing or is stopped
**Note:** Torque.js interprets the beginning and ending date/time from your "Time Column" as one block, then divides that up into [Steps]({{site.styling_cartocss}}/#-torque-frame-count-number), depending on the number you set. It does not necessarily draw one frame for each row.

View File

@ -0,0 +1,6 @@
## Layer Control Methods
Method | Options | Returns | Description
---|---|---|---
`hide()` | none | `this` | hides the Torque layer
`show()` | none| `this` | shows the Torque layer

View File

@ -0,0 +1,33 @@
## Style Methods
Method | Options | Returns | Description
---|---|---|---|
`setCartoCSS(cartocss)` | `cartocss string` | `this` | style the map rendering using client-side CartoCSS (not available with [Named maps](https://carto.com/docs/{{site.mapsapi_docs}}/guides/named-maps//maps-api/named-maps/))
Torque supports a limited subset of CartoCSS rules defined in the [torque-reference](https://github.com/cartodb/torque-reference). To see the full list of supported rules, read the [Torque CartoCSS documentation]({{site.styling_cartocss}}/#cartocss-properties-for-torque-style-maps). `value` and `zoom` variables can be used. `value` is the value of aggregation. `zoom` is the current zoom being rendered.
TorqueLayer currently expects `marker` styling.
**Example:**
```css
/* This is how a minimal example of a stylesheet for a Torque visualisation would look like. */
Map {
-torque-time-attribute: "date";
-torque-aggregation-function: "count(cartodb_id)";
-torque-frame-count: 760;
-torque-animation-duration: 15;
-torque-resolution: 2;
}
#layer {
marker-width: 3;
marker-fill-opacity: 0.8;
marker-fill: #FEE391;
}
#layer[value = 4] { // Use of the value variable, generated by the function specified in -torque-aggregation-function
marker-fill: #FABADA;
}
#layer[zoom = 12] { // Use of the zoom variable
marker-width: 10;
}
```

View File

@ -0,0 +1,12 @@
## Data Methods
Method | Options | Returns | Description
---|---|---|---
`setSQL(sql statement)` | `SQL string` | `this` | Change the SQL on the data table (not available with named maps)
`error(callback)` | `callback function with a list of errors as argument` | `this` | specifies a callback function to run if there are query errors
**Example:**
```js
// SQL Example to limit the data used in the Torque map.
torqueLayer.setSQL("SELECT * FROM table LIMIT 100");

View File

@ -0,0 +1,28 @@
## Events
Events in Torque follow the format:
```js
torqueLayer.on('event-type', function([callback_obj]) {
// do something
});
```
Events | Callback Object | Description
---|---|---
`change:steps` | current step | When a map changes steps, this event is triggered
`change:time` | current time, step number | When a map changes time, this event is triggered
`play` | none | Triggered when the Torque layer is played
`pause` | none | Triggered when the Torque layer is paused
`stop` | none | Triggered when the Torque layer is stopped
`load` | none | Triggered when the Torque layer is loaded
**Example:**
```js
// An event example to print the current step to the console log.
torqueLayer.on('change:steps', function(step) {
// do something with step
console.log('Current step is ' + step);
});
```

View File

@ -0,0 +1,12 @@
## Google Maps Layers
### GMapsTorqueLayer(_options_)
This class does exactly the same as ``L.TorqueLayer`` but using Google Maps instead. The main difference is that this class
is not a layer but is an overlay, so in order to add it to the a map use, ``layer.setMap`` instead of ``overlayMapTypes``. See the [Overlay View](https://developers.google.com/maps/documentation/javascript/reference#OverlayView) reference in Google Maps API doc.
#### Options
Name | Description
--- | ---
map | A google.maps.Map instance

View File

@ -0,0 +1,36 @@
## Support Options
Feeling stuck? There are many ways to find help.
* Ask a question on [GIS StackExchange](https://gis.stackexchange.com/questions/tagged/carto) using the `CARTO` tag.
* [Report an issue](https://github.com/CartoDB/torque/issues/new) in Github.
* Engine Plan customers have additional access to enterprise-level support through CARTO's support representatives.
If you just want to describe an issue or share an idea, just <a class="typeform-share" href="https://cartohq.typeform.com/to/mH6RRl" data-mode="popup" target="_blank"> send your feedback</a>
### Issues on Github
If you think you may have found a bug, or if you have a feature request that you would like to share with the Torque team, please [open an issue](https://github.com/CartoDB/torque/issues/new).
Before opening an issue, review the [contributing guidelines](https://github.com/CartoDB/torque/blob/master/CONTRIBUTING.md).
### Community support on GIS Stack Exchange
GIS Stack Exchange is the most popular community in the geospatial industry. This is a collaboratively-edited question and answer site for geospatial programmers and technicians. It is a fantastic resource for asking technical questions about developing and maintaining your application.
When posting a new question, please consider the following:
* Read the GIS Stack Exchange [help](https://gis.stackexchange.com/help) and [how to ask](https://gis.stackexchange.com/help/how-to-ask) pages for guidelines and tips about posting questions.
* Be very clear about your question in the subject. A clear explanation helps those trying to answer your question, as well as those who may be looking for information in the future.
* Be informative in your post. Details, code snippets, logs, screenshots, etc. help others to understand your problem.
* Use code that demonstrates the problem. It is very hard to debug errors without sample code to reproduce the problem.
### Engine Plan Customers
Engine Plan customers have additional support options beyond general community support. As per your account Terms of Service, you have access to enterprise-level support through CARTO's support representatives available at [enterprise-support@carto.com](mailto:enterprise-support@carto.com)
In order to speed up the resolution of your issue, provide as much information as possible (even if it is a link from community support). This allows our engineers to investigate your problem as soon as possible.
If you are not yet CARTO customer, browse our [plans & pricing](https://carto.com/pricing/) and find the right plan for you.

View File

@ -0,0 +1,36 @@
## Contribute
CARTO platform is an open-source ecosystem. You can read about the [fundamentals]({{site.fundamental_docs}}/components/) of CARTO architecture and its components.
We are more than happy to receive your contributions to the code and the documentation as well.
## Filling a ticket
If you want to open a new issue in our repository, please follow these instructions:
1. Descriptive title.
2. Write a good description, it always helps.
3. Specify the steps to reproduce the problem.
4. Try to add an example showing the problem.
## Contributing code
Best part of open source, collaborate in Torque.js code!. We like hearing from you, so if you have any bug fixed, or a new feature ready to be merged, those are the steps you should follow:
1. Fork the repository.
2. Create a new branch in your forked repository.
3. Commit your changes. Add new tests if it is necessary.
4. Open a pull request.
5. Any of the maintainers will take a look.
6. If everything works, it will merged and released \o/.
If you want more detailed information, this [GitHub guide](https://guides.github.com/activities/contributing-to-open-source/) is a must.
## Completing documentation
Torque.js documentation is located in ```docs/```. That folder is the content that appears in the [Developer Center](http://carto.com/developers/torque-js/). Just follow the instructions described in [contributing code](#contributing-code) and after accepting your pull request, we will make it appear online :).
**Tip:** A convenient, easy way of proposing changes in documentation is by using the GitHub editor directly on the web. You can easily create a branch with your changes and make a PR from there.
## Submitting contributions
You will need to sign a Contributor License Agreement (CLA) before making a submission. [Learn more here](https://carto.com/contributions).

View File

@ -1,57 +0,0 @@
<!DOCTYPE html>
<html>
<link rel="stylesheet" href="vendor/leaflet.css" />
<style>
#map, html, body {
width: 100%; height: 100%; padding: 0; margin: 0;
}
</style>
<body>
<div id="map"></div>
<script src="vendor/leaflet.js"></script>
<script src="vendor/carto.js"></script>
<script src="../dist/torque.uncompressed.js"></script>
<script>
var map = new L.Map('map', {
zoomControl: true,
//center: [0, 0],
center: [36.60670888641815, 38.627929687],
zoom: 6
});
L.tileLayer('http://b.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/999/256/{z}/{x}/{y}.png', {
attribution: 'Stamen'
}).addTo(map);
//type=DATASET
//var GBIF_URL = 'http://apidev.gbif.org/map/density/tile.tcjson?key=8575f23e-f762-11e1-a439-00145eb45e9a&x={x}&y={y}&z={z}&type=DATASET'
var GBIF_URL = 'http://apidev.gbif.org/map/density/tile/density/tile.tcjson?key=1&x={x}&y={y}&z={z}&type=TAXON'
var torqueLayer = new L.TiledTorqueLayer({
//url: 'http://development.localhost.lan:8080/api/v1/sql',
provider: 'url_template',
url: GBIF_URL,
resolution: 4,
cummulative: true,
start_date: 0,
end_date: 220,
step: 1,
table: 'importing_1369045322_helsinki_manydays_live',
column: 'ac',
countby: 'count(mm)',
pixel_size: 3
});
torqueLayer.addTo(map);
torqueLayer.setKey([11, 2]);
var t = 0;
setInterval(function() {
//torqueLayer.setKey(2 + (t++%11));
}, 1000);
</script>
</body>
</html>

View File

@ -1,157 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>CartoDB + Time</title>
<link rel="shortcut icon" href="http://cartodb.com/favicon/favicon_32x32.ico" />
<link href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
<style>
#torque-slider {
position:absolute;
bottom:18px;
right:25px;
width:300px;
}
#torque-pause {
position:absolute;
bottom:12px;
right:345px;
width:28px;
height: 26px;
padding: 1px 2px 2px 2px;
z-index: 1000;
border-radius: 3px;
cursor: pointer;
background-color: white;
background-image: url(../img/play.png);
background-repeat:no-repeat;
background-position:center;
}
#torque-pause.playing {
background-color: white; background-image: url(../img/pause.png); background-repeat:no-repeat; background-position:center;
}
#torque-time {
position: absolute;
top: 100px;
left: 50%;
color: white;
font-size: 31px;
font-family: Georgia, serif;
}
#map_canvas {
height: 100%;
}
</style>
</head>
<body>
<div id="map_canvas"></div>
<div id="torque-slider"></div>
<a id="torque-pause" class="playing"></a>
<div id="torque-time"></div>
<a class="cartodb_logo" href="http://www.cartodb.com" target="_blank">CartoDB</a>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script src="vendor/leaflet.js"></script>
<script src="vendor/carto.js"></script>
<script src="../dist/torque.uncompressed.js"></script>
<script type="text/javascript">
/**
* inits slider and a small play/pause button
*/
function init_slider(torqueLayer) {
var torqueTime = $('#torque-time');
$("#torque-slider").slider({
min: 0,
max: torqueLayer.options.steps,
value: 0,
step: 1,
slide: function(event, ui){
var step = ui.value;
torqueLayer.setStep(step);
}
});
// each time time changes, move the slider
torqueLayer.on('change:time', function(changes) {
$("#torque-slider" ).slider({ value: changes.step });
var month_year = changes.time.toString().substr(4).split(' ');
torqueTime.text(month_year[0] + " - " + month_year[2]);
console.log(torqueLayer.getTime());
});
// play-pause toggle
$("#torque-pause").click(function(){
torqueLayer.toggle();
$(this).toggleClass('playing');
});
};
function initialize() {
// initialise the google map
var map = new google.maps.Map(document.getElementById('map_canvas'), {
center: new google.maps.LatLng(30.95940879245423, -0.609375),
zoom: 2,
mapTypeId: google.maps.MapTypeId.SATELLITE,
mapTypeControl: false,
minZoom: 1
});
// dark map style
var gmaps_style = [{ stylers:[ { invert_lightness: true }, { weight:1 }, { saturation:-100 }, { lightness:-40 } ]
}, {
elementType:"labels",
stylers:[ { visibility:"simplified" } ]
}
];
map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
map.setOptions({ styles: gmaps_style });
// init torque layer
var torqueLayer = new torque.GMapsTorqueLayer({
user : 'viz2',
table : 'ow',
column : 'date',
countby : 'count(cartodb_id)',
steps: 750,
blendmode : 'lighter',
animationDuration: 60,
map: map
});
var DEFAULT_CARTOCSS = [
'#layer {',
" marker-width: 3; ",
' marker-fill: #FEE391; ',
' [value > 2] { marker-fill: #FEC44F; }',
' [value > 3] { marker-fill: #FE9929; }',
' [value > 4] { marker-fill: #EC7014; }',
' [value > 5] { marker-fill: #CC4C02; }',
' [value > 6] { marker-fill: #993404; }',
' [value > 7] { marker-fill: #662506; }',
' [frame-offset = 1] { marker-width: 8;marker-fill-opacity: 0.05;}',
' [frame-offset = 2] { marker-width: 20;marker-fill-opacity: 0.02;}',
//' [frame-offset = 1] { marker-width: 25;marker-fill-opacity: 0.01;}',
'}'
].join('\n');
torqueLayer.setMap(map);
torqueLayer.setCartoCSS(DEFAULT_CARTOCSS);
init_slider(torqueLayer);
torqueLayer.play();
}
window.onload = initialize;
</script>
</body>
</html>

View File

@ -1,220 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>CartoDB + Time</title>
<link rel="shortcut icon" href="http://cartodb.com/favicon/favicon_32x32.ico" />
<link href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css">
<style>
#torque-slider {
position:absolute;
bottom:18px;
right:25px;
width:300px;
}
#torque-pause {
position:absolute;
bottom:12px;
right:345px;
width:28px;
height: 26px;
padding: 1px 2px 2px 2px;
z-index: 1000;
border-radius: 3px;
cursor: pointer;
background-color: white;
background-image: url(../img/play.png);
background-repeat:no-repeat;
background-position:center;
}
#torque-pause.playing {
background-color: white; background-image: url(../img/pause.png); background-repeat:no-repeat; background-position:center;
}
#torque-time {
position: absolute;
top: 100px;
left: 50%;
color: white;
font-size: 31px;
font-family: Georgia, serif;
}
#livecode {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 450px;
padding-left: 10px;
box-shadow: 0px 0px 5px 6px #ccc;
}
textarea {
color: rgba(0,0,0,0.9);
background-color:rgba(255,255,255,0.92);
position: absolute;
left: 10px;
top: 0;
bottom: 0;
padding: 0;
margin: 0;
border: none;
font-family: monospace;
font-size: 14px;
width: 350px;
border: 0;
outline: none;
padding: 40px;
}
.highlight {
font-family: monospace;
font-size: 19px;
color: #000;
}
#credits a { color: #06c; }
#credits {
position: absolute;
bottom: 50px;
left: 40px;
font-size: 17px;
font-family: Helvetica;
}
</style>
</head>
<body>
<div id="map_canvas"></div>
<textarea id="code">
</textarea>
<div id="credits">
<p>Copy the url to share this visualization</p>
<p>Made with <a href="https://github.com/cartodb/torque">Torque</a> and <a href="http://cartodb.com">CartoDB</a></p></div>
<div id="torque-slider"></div>
<a id="torque-pause" class="playing"></a>
<div id="torque-time"></div>
<!--<a class="cartodb_logo" href="http://www.cartodb.com" target="_blank">CartoDB</a>-->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script src="vendor/leaflet.js"></script>
<script src="vendor/carto.js"></script>
<script src="../dist/torque.uncompressed.js"></script>
<script type="text/javascript">
/**
* inits slider and a small play/pause button
*/
function init_slider(torqueLayer) {
var torqueTime = $('#torque-time');
$("#torque-slider").slider({
min: 0,
max: torqueLayer.options.steps,
value: 0,
step: 1,
slide: function(event, ui){
var step = ui.value;
torqueLayer.setStep(step);
}
});
// each time time changes, move the slider
torqueLayer.on('change:time', function(changes) {
$("#torque-slider" ).slider({ value: changes.step });
var month_year = changes.time.toString().substr(4).split(' ');
torqueTime.text(month_year[0] + " - " + month_year[2]);
console.log(torqueLayer.getTime());
});
// play-pause toggle
$("#torque-pause").click(function(){
torqueLayer.toggle();
$(this).toggleClass('playing');
});
};
function initialize() {
// initialise the google map
var map = new google.maps.Map(document.getElementById('map_canvas'), {
center: new google.maps.LatLng(30.95940879245423, -0.609375),
zoom: 2,
mapTypeId: google.maps.MapTypeId.SATELLITE,
mapTypeControl: false,
minZoom: 1
});
// dark map style
var gmaps_style = [{ stylers:[ { invert_lightness: true }, { weight:1 }, { saturation:-100 }, { lightness:-40 } ]
}, {
elementType:"labels",
stylers:[ { visibility:"simplified" } ]
}
];
map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
map.setOptions({ styles: gmaps_style });
// init torque layer
var torqueLayer = new torque.GMapsTorqueLayer({
user : 'viz2',
table : 'ow',
column : 'date',
countby : 'count(cartodb_id)',
resolution: 1,
steps: 750,
blendmode : 'lighter',
animationDuration: 60,
map: map
});
var DEFAULT_CARTOCSS = [
'#layer {',
' marker-width: 2; ',
' marker-fill: #FEE391; ',
' [value > 2] { marker-fill: #FEC44F; }',
' [value > 3] { marker-fill: #FE9929; }',
' [value > 4] { marker-fill: #EC7014; }',
' [value > 5] { marker-fill: #CC4C02; }',
' [value > 6] { marker-fill: #993404; }',
' [value > 7] { marker-fill: #662506; }',
'',
'}',
'',
'#layer [frame-offset = 1] { ',
' marker-fill: #FEE391; ',
' marker-width: 8;',
' marker-fill-opacity: 0.05;',
'}',
'',
'#layer [frame-offset = 2] { ',
' marker-fill: #FEE391; ',
' marker-width: 20;',
' marker-fill-opacity: 0.02;',
'}'
].join('\n');
var code = $('#code')
code.on('keyup', function() {
torqueLayer.setCartoCSS(code.val());
location.hash = btoa(code.val());
});
torqueLayer.setMap(map);
var css = location.hash ? atob(location.hash.substring(1)): DEFAULT_CARTOCSS;
torqueLayer.setCartoCSS(css)
code.val(css);
init_slider(torqueLayer);
torqueLayer.play();
}
window.onload = initialize;
</script>
</body>
</html>

View File

@ -1,164 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>CartoDB + Time</title>
<link rel="shortcut icon" href="http://cartodb.com/favicon/favicon_32x32.ico" />
<link href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="../lib/cartodb.css">
<link rel="stylesheet" href="../css/jqueryui-smoothness/jquery-ui-1.10.2.custom.min.css">
<style>
#torque-slider{
position:absolute;
bottom:18px;
right:25px;
width:300px;
}
#torque-pause{
position:absolute;
bottom:12px;
right:345px;
width:28px;
height: 26px;
padding: 1px 2px 2px 2px;
z-index: 1000;
border-radius: 3px;
cursor: pointer;
}
.playing {background-color: white; background-image: url(../img/pause.png); background-repeat:no-repeat; background-position:center; }
.paused { background-color: white; background-image: url(../img/play.png);background-repeat:no-repeat; background-position:center;}
/* #torque-pause .playing {
background-image: url('../img/pause.png');
}
#torque-pause .paused{
background-image: url('../img/play.png');
}*/
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="../lib/jquery-ui-1.10.2.custom.min.js"></script>
<script type="text/javascript" src="../lib/wax.g.js"></script>
<script type="text/javascript" src="../lib/cartodb-gmapsv3.js"></script>
<script type="text/javascript" src="../lib/dat.gui.min.js"></script>
<script type="text/javascript" src="../lib/underscore-min.js"></script>
<script type="text/javascript" src="../lib/backbone.js"></script>
<script type="text/javascript" src="../lib/class.js"></script>
<script type="text/javascript" src="../lib/backbone.cartodb.js"></script>
<script type="text/javascript" src="../src/canvas_tile_layer.js"></script>
<script type="text/javascript" src="../src/grid_layer.js"></script>
<script type="text/javascript" src="../src/torque.js"></script>
<script type="text/javascript">
var gui;
function initialize() {
// initialise the google map
var map = new google.maps.Map(document.getElementById('map_canvas'), {
center:new google.maps.LatLng(30.95940879245423, -0.609375),
zoom:2,
mapTypeId:google.maps.MapTypeId.SATELLITE,
mapTypeControl:false,
minZoom:1
});
var map_style = {};
map_style.google_maps_customization_style = [
{
stylers:[
{ invert_lightness:true },
{ weight:1 },
{ saturation:-100 },
{ lightness:-40 }
]
},
{
elementType:"labels",
stylers:[
{ visibility:"simplified" }
]
}
];
var Soft = function () {
this.Soft = function () {
map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
map.setOptions({styles:map_style.google_maps_customization_style});
}
}
map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
map.setOptions({styles:map_style.google_maps_customization_style});
function init_slider( that ){
var that_opts = that.options;
$('body').append('<div id="torque-slider"></div>');
// Init jQuery UI options
$("#torque-slider").slider({
min: Math.round(that_opts.start),
max: Math.floor(that_opts.end),
value: Math.round(that_opts.start),
step: that._step,
slide: function(event, ui){
that._current = ui.value;
var date = new Date(that._current * 1000);
var date_arry = date.toString().substr(4).split(' ');
that._display.set_time((that._current - that.start) / that._step);
}
});
};
function on_move (that) {
$( "#torque-slider" ).slider({ value: that._current });
}
var TorqueOptions = {
user:'osm2',
table:'ship_flight_recorder',
column:'toc',
steps:140,
resolution:2,
cumulative:false,
clock:true,
fps:11,
fitbounds:false,
blendmode:'lighter',
trails:true,
point_type:'circle',
cellsize:1,
scrub: init_slider,
scrub_move: on_move
}
var torque = null;
Torque(function (env) {
Torque.app = new env.app.Instance();
torque = new Torque.app.addLayer(map, TorqueOptions);
Torque.env = env;
// TODO pause method needs to be added to Torque UI options
var pause = $('<a></a>');
$(pause).attr('id','torque-pause')
$(pause).addClass("playing");
$('body').append(pause);
$(pause).click(function(){
if($(this).hasClass('paused')){
torque.pause();
$(this).removeClass("paused");
$(this).addClass("playing");
} else {
$(this).removeClass("playing");
$(this).addClass("paused");
torque.pause();
}
});
});
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas"></div>
<div class="torque_time"></div>
<a class="cartodb_logo" href="http://www.cartodb.com" target="_blank">CartoDB</a>
</body>
</html>

8625
examples/vendor/carto.js vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,263 +0,0 @@
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: 300px;
}
.CodeMirror-scroll {
/* Set scrolling behaviour here */
overflow: auto;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
}
/* CURSOR */
.CodeMirror div.CodeMirror-cursor {
border-left: 1px solid black;
z-index: 3;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
width: auto;
border: 0;
background: #7e7;
z-index: 1;
}
/* Can style cursor different in overwrite (non-insert) mode */
.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
.cm-tab { display: inline-block; }
/* DEFAULT THEME */
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable {color: black;}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;}
.cm-s-default .cm-property {color: black;}
.cm-s-default .cm-operator {color: black;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-error {color: #f00;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}
.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-invalidchar {color: #f00;}
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
line-height: 1;
position: relative;
overflow: hidden;
background: white;
color: black;
}
.CodeMirror-scroll {
/* 30px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -30px; margin-right: -30px;
padding-bottom: 30px; padding-right: 30px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-sizer {
position: relative;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actuall scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
overflow-x: hidden;
overflow-y: scroll;
}
.CodeMirror-hscrollbar {
bottom: 0; left: 0;
overflow-y: hidden;
overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
padding-bottom: 30px;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
-moz-box-sizing: content-box;
box-sizing: content-box;
padding-bottom: 30px;
margin-bottom: -32px;
display: inline-block;
/* Hack to make IE7 behave */
*zoom:1;
*display:inline;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-lines {
cursor: text;
}
.CodeMirror pre {
/* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0;
background: transparent;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-code pre {
border-right: 30px solid transparent;
width: -webkit-fit-content;
width: -moz-fit-content;
width: fit-content;
}
.CodeMirror-wrap .CodeMirror-code pre {
border-right: none;
width: auto;
}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
overflow: auto;
}
.CodeMirror-widget {}
.CodeMirror-wrap .CodeMirror-scroll {
overflow-x: hidden;
}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden;
}
.CodeMirror-measure pre { position: static; }
.CodeMirror div.CodeMirror-cursor {
position: absolute;
visibility: hidden;
border-right: none;
width: 0;
}
.CodeMirror-focused div.CodeMirror-cursor {
visibility: visible;
}
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.cm-searching {
background: #ffa;
background: rgba(255, 255, 0, .4);
}
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursor {
visibility: hidden;
}
}

File diff suppressed because it is too large Load Diff

639
examples/vendor/css.js vendored
View File

@ -1,639 +0,0 @@
CodeMirror.defineMode("css", function(config, parserConfig) {
"use strict";
if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
var indentUnit = config.indentUnit || config.tabSize || 2,
hooks = parserConfig.hooks || {},
atMediaTypes = parserConfig.atMediaTypes || {},
atMediaFeatures = parserConfig.atMediaFeatures || {},
propertyKeywords = parserConfig.propertyKeywords || {},
colorKeywords = parserConfig.colorKeywords || {},
valueKeywords = parserConfig.valueKeywords || {},
allowNested = !!parserConfig.allowNested,
type = null;
function ret(style, tp) { type = tp; return style; }
function tokenBase(stream, state) {
var ch = stream.next();
if (hooks[ch]) {
// result[0] is style and result[1] is type
var result = hooks[ch](stream, state);
if (result !== false) return result;
}
if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("def", stream.current());}
else if (ch == "=") ret(null, "compare");
else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare");
else if (ch == "\"" || ch == "'") {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
}
else if (ch == "#") {
stream.eatWhile(/[\w\\\-]/);
return ret("atom", "hash");
}
else if (ch == "!") {
stream.match(/^\s*\w*/);
return ret("keyword", "important");
}
else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
stream.eatWhile(/[\w.%]/);
return ret("number", "unit");
}
else if (ch === "-") {
if (/\d/.test(stream.peek())) {
stream.eatWhile(/[\w.%]/);
return ret("number", "unit");
} else if (stream.match(/^[^-]+-/)) {
return ret("meta", "meta");
}
}
else if (/[,+>*\/]/.test(ch)) {
return ret(null, "select-op");
}
else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
return ret("qualifier", "qualifier");
}
else if (ch == ":") {
return ret("operator", ch);
}
else if (/[;{}\[\]\(\)]/.test(ch)) {
return ret(null, ch);
}
else if (ch == "u" && stream.match("rl(")) {
stream.backUp(1);
state.tokenize = tokenParenthesized;
return ret("property", "variable");
}
else {
stream.eatWhile(/[\w\\\-]/);
return ret("property", "variable");
}
}
function tokenString(quote, nonInclusive) {
return function(stream, state) {
var escaped = false, ch;
while ((ch = stream.next()) != null) {
if (ch == quote && !escaped)
break;
escaped = !escaped && ch == "\\";
}
if (!escaped) {
if (nonInclusive) stream.backUp(1);
state.tokenize = tokenBase;
}
return ret("string", "string");
};
}
function tokenParenthesized(stream, state) {
stream.next(); // Must be '('
if (!stream.match(/\s*[\"\']/, false))
state.tokenize = tokenString(")", true);
else
state.tokenize = tokenBase;
return ret(null, "(");
}
return {
startState: function(base) {
return {tokenize: tokenBase,
baseIndent: base || 0,
stack: [],
lastToken: null};
},
token: function(stream, state) {
// Use these terms when applicable (see http://www.xanthir.com/blog/b4E50)
//
// rule** or **ruleset:
// A selector + braces combo, or an at-rule.
//
// declaration block:
// A sequence of declarations.
//
// declaration:
// A property + colon + value combo.
//
// property value:
// The entire value of a property.
//
// component value:
// A single piece of a property value. Like the 5px in
// text-shadow: 0 0 5px blue;. Can also refer to things that are
// multiple terms, like the 1-4 terms that make up the background-size
// portion of the background shorthand.
//
// term:
// The basic unit of author-facing CSS, like a single number (5),
// dimension (5px), string ("foo"), or function. Officially defined
// by the CSS 2.1 grammar (look for the 'term' production)
//
//
// simple selector:
// A single atomic selector, like a type selector, an attr selector, a
// class selector, etc.
//
// compound selector:
// One or more simple selectors without a combinator. div.example is
// compound, div > .example is not.
//
// complex selector:
// One or more compound selectors chained with combinators.
//
// combinator:
// The parts of selectors that express relationships. There are four
// currently - the space (descendant combinator), the greater-than
// bracket (child combinator), the plus sign (next sibling combinator),
// and the tilda (following sibling combinator).
//
// sequence of selectors:
// One or more of the named type of selector chained with commas.
state.tokenize = state.tokenize || tokenBase;
if (state.tokenize == tokenBase && stream.eatSpace()) return null;
var style = state.tokenize(stream, state);
if (style && typeof style != "string") style = ret(style[0], style[1]);
// Changing style returned based on context
var context = state.stack[state.stack.length-1];
if (style == "variable") {
if (type == "variable-definition") state.stack.push("propertyValue");
return state.lastToken = "variable-2";
} else if (style == "property") {
var word = stream.current().toLowerCase();
if (context == "propertyValue") {
if (valueKeywords.hasOwnProperty(word)) {
style = "string-2";
} else if (colorKeywords.hasOwnProperty(word)) {
style = "keyword";
} else {
style = "variable-2";
}
} else if (context == "rule") {
if (!propertyKeywords.hasOwnProperty(word)) {
style += " error";
}
} else if (context == "block") {
// if a value is present in both property, value, or color, the order
// of preference is property -> color -> value
if (propertyKeywords.hasOwnProperty(word)) {
style = "property";
} else if (colorKeywords.hasOwnProperty(word)) {
style = "keyword";
} else if (valueKeywords.hasOwnProperty(word)) {
style = "string-2";
} else {
style = "tag";
}
} else if (!context || context == "@media{") {
style = "tag";
} else if (context == "@media") {
if (atMediaTypes[stream.current()]) {
style = "attribute"; // Known attribute
} else if (/^(only|not)$/.test(word)) {
style = "keyword";
} else if (word == "and") {
style = "error"; // "and" is only allowed in @mediaType
} else if (atMediaFeatures.hasOwnProperty(word)) {
style = "error"; // Known property, should be in @mediaType(
} else {
// Unknown, expecting keyword or attribute, assuming attribute
style = "attribute error";
}
} else if (context == "@mediaType") {
if (atMediaTypes.hasOwnProperty(word)) {
style = "attribute";
} else if (word == "and") {
style = "operator";
} else if (/^(only|not)$/.test(word)) {
style = "error"; // Only allowed in @media
} else {
// Unknown attribute or property, but expecting property (preceded
// by "and"). Should be in parentheses
style = "error";
}
} else if (context == "@mediaType(") {
if (propertyKeywords.hasOwnProperty(word)) {
// do nothing, remains "property"
} else if (atMediaTypes.hasOwnProperty(word)) {
style = "error"; // Known property, should be in parentheses
} else if (word == "and") {
style = "operator";
} else if (/^(only|not)$/.test(word)) {
style = "error"; // Only allowed in @media
} else {
style += " error";
}
} else if (context == "@import") {
style = "tag";
} else {
style = "error";
}
} else if (style == "atom") {
if(!context || context == "@media{" || context == "block") {
style = "builtin";
} else if (context == "propertyValue") {
if (!/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) {
style += " error";
}
} else {
style = "error";
}
} else if (context == "@media" && type == "{") {
style = "error";
}
// Push/pop context stack
if (type == "{") {
if (context == "@media" || context == "@mediaType") {
state.stack[state.stack.length-1] = "@media{";
}
else {
var newContext = allowNested ? "block" : "rule";
state.stack.push(newContext);
}
}
else if (type == "}") {
if (context == "interpolation") style = "operator";
// Pop off end of array until { is reached
while(state.stack.length){
var removed = state.stack.pop();
if(removed.indexOf("{") > -1){
break;
}
}
}
else if (type == "interpolation") state.stack.push("interpolation");
else if (type == "@media") state.stack.push("@media");
else if (type == "@import") state.stack.push("@import");
else if (context == "@media" && /\b(keyword|attribute)\b/.test(style))
state.stack[state.stack.length-1] = "@mediaType";
else if (context == "@mediaType" && stream.current() == ",")
state.stack[state.stack.length-1] = "@media";
else if (type == "(") {
if (context == "@media" || context == "@mediaType") {
// Make sure @mediaType is used to avoid error on {
state.stack[state.stack.length-1] = "@mediaType";
state.stack.push("@mediaType(");
}
else state.stack.push("(");
}
else if (type == ")") {
// Pop off end of array until ( is reached
while(state.stack.length){
var removed = state.stack.pop();
if(removed.indexOf("(") > -1){
break;
}
}
}
else if (type == ":" && state.lastToken == "property") state.stack.push("propertyValue");
else if (context == "propertyValue" && type == ";") state.stack.pop();
else if (context == "@import" && type == ";") state.stack.pop();
return state.lastToken = style;
},
indent: function(state, textAfter) {
var n = state.stack.length;
if (/^\}/.test(textAfter))
n -= state.stack[n-1] == "propertyValue" ? 2 : 1;
return state.baseIndent + n * indentUnit;
},
electricChars: "}",
blockCommentStart: "/*",
blockCommentEnd: "*/",
fold: "brace"
};
});
(function() {
function keySet(array) {
var keys = {};
for (var i = 0; i < array.length; ++i) {
keys[array[i]] = true;
}
return keys;
}
var atMediaTypes = keySet([
"all", "aural", "braille", "handheld", "print", "projection", "screen",
"tty", "tv", "embossed"
]);
var atMediaFeatures = keySet([
"width", "min-width", "max-width", "height", "min-height", "max-height",
"device-width", "min-device-width", "max-device-width", "device-height",
"min-device-height", "max-device-height", "aspect-ratio",
"min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
"min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
"max-color", "color-index", "min-color-index", "max-color-index",
"monochrome", "min-monochrome", "max-monochrome", "resolution",
"min-resolution", "max-resolution", "scan", "grid"
]);
var propertyKeywords = keySet([
"align-content", "align-items", "align-self", "alignment-adjust",
"alignment-baseline", "anchor-point", "animation", "animation-delay",
"animation-direction", "animation-duration", "animation-iteration-count",
"animation-name", "animation-play-state", "animation-timing-function",
"appearance", "azimuth", "backface-visibility", "background",
"background-attachment", "background-clip", "background-color",
"background-image", "background-origin", "background-position",
"background-repeat", "background-size", "baseline-shift", "binding",
"bleed", "bookmark-label", "bookmark-level", "bookmark-state",
"bookmark-target", "border", "border-bottom", "border-bottom-color",
"border-bottom-left-radius", "border-bottom-right-radius",
"border-bottom-style", "border-bottom-width", "border-collapse",
"border-color", "border-image", "border-image-outset",
"border-image-repeat", "border-image-slice", "border-image-source",
"border-image-width", "border-left", "border-left-color",
"border-left-style", "border-left-width", "border-radius", "border-right",
"border-right-color", "border-right-style", "border-right-width",
"border-spacing", "border-style", "border-top", "border-top-color",
"border-top-left-radius", "border-top-right-radius", "border-top-style",
"border-top-width", "border-width", "bottom", "box-decoration-break",
"box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
"caption-side", "clear", "clip", "color", "color-profile", "column-count",
"column-fill", "column-gap", "column-rule", "column-rule-color",
"column-rule-style", "column-rule-width", "column-span", "column-width",
"columns", "content", "counter-increment", "counter-reset", "crop", "cue",
"cue-after", "cue-before", "cursor", "direction", "display",
"dominant-baseline", "drop-initial-after-adjust",
"drop-initial-after-align", "drop-initial-before-adjust",
"drop-initial-before-align", "drop-initial-size", "drop-initial-value",
"elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
"flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
"float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
"font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
"font-stretch", "font-style", "font-synthesis", "font-variant",
"font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
"font-variant-ligatures", "font-variant-numeric", "font-variant-position",
"font-weight", "grid-cell", "grid-column", "grid-column-align",
"grid-column-sizing", "grid-column-span", "grid-columns", "grid-flow",
"grid-row", "grid-row-align", "grid-row-sizing", "grid-row-span",
"grid-rows", "grid-template", "hanging-punctuation", "height", "hyphens",
"icon", "image-orientation", "image-rendering", "image-resolution",
"inline-box-align", "justify-content", "left", "letter-spacing",
"line-break", "line-height", "line-stacking", "line-stacking-ruby",
"line-stacking-shift", "line-stacking-strategy", "list-style",
"list-style-image", "list-style-position", "list-style-type", "margin",
"margin-bottom", "margin-left", "margin-right", "margin-top",
"marker-offset", "marks", "marquee-direction", "marquee-loop",
"marquee-play-count", "marquee-speed", "marquee-style", "max-height",
"max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
"nav-left", "nav-right", "nav-up", "opacity", "order", "orphans", "outline",
"outline-color", "outline-offset", "outline-style", "outline-width",
"overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
"padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
"page", "page-break-after", "page-break-before", "page-break-inside",
"page-policy", "pause", "pause-after", "pause-before", "perspective",
"perspective-origin", "pitch", "pitch-range", "play-during", "position",
"presentation-level", "punctuation-trim", "quotes", "region-break-after",
"region-break-before", "region-break-inside", "region-fragment",
"rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
"right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
"ruby-position", "ruby-span", "shape-inside", "shape-outside", "size",
"speak", "speak-as", "speak-header",
"speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
"tab-size", "table-layout", "target", "target-name", "target-new",
"target-position", "text-align", "text-align-last", "text-decoration",
"text-decoration-color", "text-decoration-line", "text-decoration-skip",
"text-decoration-style", "text-emphasis", "text-emphasis-color",
"text-emphasis-position", "text-emphasis-style", "text-height",
"text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow",
"text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position",
"text-wrap", "top", "transform", "transform-origin", "transform-style",
"transition", "transition-delay", "transition-duration",
"transition-property", "transition-timing-function", "unicode-bidi",
"vertical-align", "visibility", "voice-balance", "voice-duration",
"voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
"voice-volume", "volume", "white-space", "widows", "width", "word-break",
"word-spacing", "word-wrap", "z-index", "zoom",
// SVG-specific
"clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
"flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
"color-interpolation", "color-interpolation-filters", "color-profile",
"color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
"marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
"stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
"stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
"baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
"glyph-orientation-vertical", "kerning", "text-anchor", "writing-mode"
]);
var colorKeywords = keySet([
"aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
"bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
"burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
"cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
"darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
"darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
"darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
"deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
"floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
"gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
"hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
"lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
"lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
"lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
"lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
"maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
"mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
"mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
"navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
"orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
"papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
"purple", "red", "rosybrown", "royalblue", "saddlebrown", "salmon",
"sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
"slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
"teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
"whitesmoke", "yellow", "yellowgreen"
]);
var valueKeywords = keySet([
"above", "absolute", "activeborder", "activecaption", "afar",
"after-white-space", "ahead", "alias", "all", "all-scroll", "alternate",
"always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
"arabic-indic", "armenian", "asterisks", "auto", "avoid", "avoid-column", "avoid-page",
"avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
"bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
"both", "bottom", "break", "break-all", "break-word", "button", "button-bevel",
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian",
"capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
"cell", "center", "checkbox", "circle", "cjk-earthly-branch",
"cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
"col-resize", "collapse", "column", "compact", "condensed", "contain", "content",
"content-box", "context-menu", "continuous", "copy", "cover", "crop",
"cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal",
"decimal-leading-zero", "default", "default-button", "destination-atop",
"destination-in", "destination-out", "destination-over", "devanagari",
"disc", "discard", "document", "dot-dash", "dot-dot-dash", "dotted",
"double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
"element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
"ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
"ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
"ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
"ethiopic-halehame-gez", "ethiopic-halehame-om-et",
"ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
"ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et",
"ethiopic-halehame-tig", "ew-resize", "expanded", "extra-condensed",
"extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes",
"forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
"gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew",
"help", "hidden", "hide", "higher", "highlight", "highlighttext",
"hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
"infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
"inline-block", "inline-table", "inset", "inside", "intrinsic", "invert",
"italic", "justify", "kannada", "katakana", "katakana-iroha", "keep-all", "khmer",
"landscape", "lao", "large", "larger", "left", "level", "lighter",
"line-through", "linear", "lines", "list-item", "listbox", "listitem",
"local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
"lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
"lower-roman", "lowercase", "ltr", "malayalam", "match",
"media-controls-background", "media-current-time-display",
"media-fullscreen-button", "media-mute-button", "media-play-button",
"media-return-to-realtime-button", "media-rewind-button",
"media-seek-back-button", "media-seek-forward-button", "media-slider",
"media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
"media-volume-slider-container", "media-volume-sliderthumb", "medium",
"menu", "menulist", "menulist-button", "menulist-text",
"menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
"mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize",
"narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
"no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
"ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
"optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
"outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
"painted", "page", "paused", "persian", "plus-darker", "plus-lighter", "pointer",
"polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button",
"radio", "read-only", "read-write", "read-write-plaintext-only", "rectangle", "region",
"relative", "repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba",
"ridge", "right", "round", "row-resize", "rtl", "run-in", "running",
"s-resize", "sans-serif", "scroll", "scrollbar", "se-resize", "searchfield",
"searchfield-cancel-button", "searchfield-decoration",
"searchfield-results-button", "searchfield-results-decoration",
"semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
"single", "skip-white-space", "slide", "slider-horizontal",
"slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
"small", "small-caps", "small-caption", "smaller", "solid", "somali",
"source-atop", "source-in", "source-out", "source-over", "space", "square",
"square-button", "start", "static", "status-bar", "stretch", "stroke",
"sub", "subpixel-antialiased", "super", "sw-resize", "table",
"table-caption", "table-cell", "table-column", "table-column-group",
"table-footer-group", "table-header-group", "table-row", "table-row-group",
"telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
"thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
"threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
"tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
"transparent", "ultra-condensed", "ultra-expanded", "underline", "up",
"upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
"upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
"vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
"visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
"window", "windowframe", "windowtext", "x-large", "x-small", "xor",
"xx-large", "xx-small"
]);
function tokenCComment(stream, state) {
var maybeEnd = false, ch;
while ((ch = stream.next()) != null) {
if (maybeEnd && ch == "/") {
state.tokenize = null;
break;
}
maybeEnd = (ch == "*");
}
return ["comment", "comment"];
}
CodeMirror.defineMIME("text/css", {
atMediaTypes: atMediaTypes,
atMediaFeatures: atMediaFeatures,
propertyKeywords: propertyKeywords,
colorKeywords: colorKeywords,
valueKeywords: valueKeywords,
hooks: {
"<": function(stream, state) {
function tokenSGMLComment(stream, state) {
var dashes = 0, ch;
while ((ch = stream.next()) != null) {
if (dashes >= 2 && ch == ">") {
state.tokenize = null;
break;
}
dashes = (ch == "-") ? dashes + 1 : 0;
}
return ["comment", "comment"];
}
if (stream.eat("!")) {
state.tokenize = tokenSGMLComment;
return tokenSGMLComment(stream, state);
}
},
"/": function(stream, state) {
if (stream.eat("*")) {
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
}
return false;
}
},
name: "css"
});
CodeMirror.defineMIME("text/x-scss", {
atMediaTypes: atMediaTypes,
atMediaFeatures: atMediaFeatures,
propertyKeywords: propertyKeywords,
colorKeywords: colorKeywords,
valueKeywords: valueKeywords,
allowNested: true,
hooks: {
":": function(stream) {
if (stream.match(/\s*{/)) {
return [null, "{"];
}
return false;
},
"$": function(stream) {
stream.match(/^[\w-]+/);
if (stream.peek() == ":") {
return ["variable", "variable-definition"];
}
return ["variable", "variable"];
},
",": function(_stream, state) {
if (state.stack[state.stack.length - 1] == "propertyValue") {
return ["operator", ";"];
}
},
"/": function(stream, state) {
if (stream.eat("/")) {
stream.skipToEnd();
return ["comment", "comment"];
} else if (stream.eat("*")) {
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
} else {
return ["operator", "operator"];
}
},
"#": function(stream) {
if (stream.eat("{")) {
return ["operator", "interpolation"];
} else {
stream.eatWhile(/[\w\\\-]/);
return ["atom", "hash"];
}
}
},
name: "css"
});
})();

File diff suppressed because one or more lines are too long

View File

@ -1,478 +0,0 @@
/* required styles */
.leaflet-map-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-pane,
.leaflet-tile-container,
.leaflet-overlay-pane,
.leaflet-shadow-pane,
.leaflet-marker-pane,
.leaflet-popup-pane,
.leaflet-overlay-pane svg,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
position: absolute;
left: 0;
top: 0;
}
.leaflet-container {
overflow: hidden;
-ms-touch-action: none;
}
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-user-drag: none;
}
.leaflet-marker-icon,
.leaflet-marker-shadow {
display: block;
}
/* map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container img {
max-width: none !important;
}
/* stupid Android 2 doesn't understand "max-width: none" properly */
.leaflet-container img.leaflet-image-layer {
max-width: 15000px !important;
}
.leaflet-tile {
filter: inherit;
visibility: hidden;
}
.leaflet-tile-loaded {
visibility: inherit;
}
.leaflet-zoom-box {
width: 0;
height: 0;
}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
-moz-user-select: none;
}
.leaflet-tile-pane { z-index: 2; }
.leaflet-objects-pane { z-index: 3; }
.leaflet-overlay-pane { z-index: 4; }
.leaflet-shadow-pane { z-index: 5; }
.leaflet-marker-pane { z-index: 6; }
.leaflet-popup-pane { z-index: 7; }
.leaflet-vml-shape {
width: 1px;
height: 1px;
}
.lvml {
behavior: url(#default#VML);
display: inline-block;
position: absolute;
}
/* control positioning */
.leaflet-control {
position: relative;
z-index: 7;
pointer-events: auto;
}
.leaflet-top,
.leaflet-bottom {
position: absolute;
z-index: 1000;
pointer-events: none;
}
.leaflet-top {
top: 0;
}
.leaflet-right {
right: 0;
}
.leaflet-bottom {
bottom: 0;
}
.leaflet-left {
left: 0;
}
.leaflet-control {
float: left;
clear: both;
}
.leaflet-right .leaflet-control {
float: right;
}
.leaflet-top .leaflet-control {
margin-top: 10px;
}
.leaflet-bottom .leaflet-control {
margin-bottom: 10px;
}
.leaflet-left .leaflet-control {
margin-left: 10px;
}
.leaflet-right .leaflet-control {
margin-right: 10px;
}
/* zoom and fade animations */
.leaflet-fade-anim .leaflet-tile,
.leaflet-fade-anim .leaflet-popup {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
-o-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.leaflet-fade-anim .leaflet-tile-loaded,
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
opacity: 1;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
-o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1);
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile,
.leaflet-touching .leaflet-zoom-animated {
-webkit-transition: none;
-moz-transition: none;
-o-transition: none;
transition: none;
}
.leaflet-zoom-anim .leaflet-zoom-hide {
visibility: hidden;
}
/* cursors */
.leaflet-clickable {
cursor: pointer;
}
.leaflet-container {
cursor: -webkit-grab;
cursor: -moz-grab;
}
.leaflet-popup-pane,
.leaflet-control {
cursor: auto;
}
.leaflet-dragging .leaflet-container,
.leaflet-dragging .leaflet-clickable {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
}
/* visual tweaks */
.leaflet-container {
background: #ddd;
outline: 0;
}
.leaflet-container a {
color: #0078A8;
}
.leaflet-container a.leaflet-active {
outline: 2px solid orange;
}
.leaflet-zoom-box {
border: 2px dotted #38f;
background: rgba(255,255,255,0.5);
}
/* general typography */
.leaflet-container {
font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
}
/* general toolbar styles */
.leaflet-bar {
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
border-radius: 4px;
}
.leaflet-bar a,
.leaflet-bar a:hover {
background-color: #fff;
border-bottom: 1px solid #ccc;
width: 26px;
height: 26px;
line-height: 26px;
display: block;
text-align: center;
text-decoration: none;
color: black;
}
.leaflet-bar a,
.leaflet-control-layers-toggle {
background-position: 50% 50%;
background-repeat: no-repeat;
display: block;
}
.leaflet-bar a:hover {
background-color: #f4f4f4;
}
.leaflet-bar a:first-child {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.leaflet-bar a:last-child {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom: none;
}
.leaflet-bar a.leaflet-disabled {
cursor: default;
background-color: #f4f4f4;
color: #bbb;
}
.leaflet-touch .leaflet-bar a {
width: 30px;
height: 30px;
line-height: 30px;
}
/* zoom control */
.leaflet-control-zoom-in,
.leaflet-control-zoom-out {
font: bold 18px 'Lucida Console', Monaco, monospace;
text-indent: 1px;
}
.leaflet-control-zoom-out {
font-size: 20px;
}
.leaflet-touch .leaflet-control-zoom-in {
font-size: 22px;
}
.leaflet-touch .leaflet-control-zoom-out {
font-size: 24px;
}
/* layers control */
.leaflet-control-layers {
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
background: #fff;
border-radius: 5px;
}
.leaflet-control-layers-toggle {
background-image: url(images/layers.png);
width: 36px;
height: 36px;
}
.leaflet-retina .leaflet-control-layers-toggle {
background-image: url(images/layers-2x.png);
background-size: 26px 26px;
}
.leaflet-touch .leaflet-control-layers-toggle {
width: 44px;
height: 44px;
}
.leaflet-control-layers .leaflet-control-layers-list,
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
display: none;
}
.leaflet-control-layers-expanded .leaflet-control-layers-list {
display: block;
position: relative;
}
.leaflet-control-layers-expanded {
padding: 6px 10px 6px 6px;
color: #333;
background: #fff;
}
.leaflet-control-layers-selector {
margin-top: 2px;
position: relative;
top: 1px;
}
.leaflet-control-layers label {
display: block;
}
.leaflet-control-layers-separator {
height: 0;
border-top: 1px solid #ddd;
margin: 5px -10px 5px -6px;
}
/* attribution and scale controls */
.leaflet-container .leaflet-control-attribution {
background: #fff;
background: rgba(255, 255, 255, 0.7);
margin: 0;
}
.leaflet-control-attribution,
.leaflet-control-scale-line {
padding: 0 5px;
color: #333;
}
.leaflet-control-attribution a {
text-decoration: none;
}
.leaflet-control-attribution a:hover {
text-decoration: underline;
}
.leaflet-container .leaflet-control-attribution,
.leaflet-container .leaflet-control-scale {
font-size: 11px;
}
.leaflet-left .leaflet-control-scale {
margin-left: 5px;
}
.leaflet-bottom .leaflet-control-scale {
margin-bottom: 5px;
}
.leaflet-control-scale-line {
border: 2px solid #777;
border-top: none;
line-height: 1.1;
padding: 2px 5px 1px;
font-size: 11px;
white-space: nowrap;
overflow: hidden;
-moz-box-sizing: content-box;
box-sizing: content-box;
background: #fff;
background: rgba(255, 255, 255, 0.5);
}
.leaflet-control-scale-line:not(:first-child) {
border-top: 2px solid #777;
border-bottom: none;
margin-top: -2px;
}
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
border-bottom: 2px solid #777;
}
.leaflet-touch .leaflet-control-attribution,
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
box-shadow: none;
}
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
}
/* popup */
.leaflet-popup {
position: absolute;
text-align: center;
}
.leaflet-popup-content-wrapper {
padding: 1px;
text-align: left;
border-radius: 12px;
}
.leaflet-popup-content {
margin: 13px 19px;
line-height: 1.4;
}
.leaflet-popup-content p {
margin: 18px 0;
}
.leaflet-popup-tip-container {
margin: 0 auto;
width: 40px;
height: 20px;
position: relative;
overflow: hidden;
}
.leaflet-popup-tip {
width: 17px;
height: 17px;
padding: 1px;
margin: -10px auto 0;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
background: white;
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
}
.leaflet-container a.leaflet-popup-close-button {
position: absolute;
top: 0;
right: 0;
padding: 4px 4px 0 0;
text-align: center;
width: 18px;
height: 14px;
font: 16px/14px Tahoma, Verdana, sans-serif;
color: #c3c3c3;
text-decoration: none;
font-weight: bold;
background: transparent;
}
.leaflet-container a.leaflet-popup-close-button:hover {
color: #999;
}
.leaflet-popup-scrolled {
overflow: auto;
border-bottom: 1px solid #ddd;
border-top: 1px solid #ddd;
}
.leaflet-oldie .leaflet-popup-content-wrapper {
zoom: 1;
}
.leaflet-oldie .leaflet-popup-tip {
width: 24px;
margin: 0 auto;
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
}
.leaflet-oldie .leaflet-popup-tip-container {
margin-top: -1px;
}
.leaflet-oldie .leaflet-control-zoom,
.leaflet-oldie .leaflet-control-layers,
.leaflet-oldie .leaflet-popup-content-wrapper,
.leaflet-oldie .leaflet-popup-tip {
border: 1px solid #999;
}
/* div icon */
.leaflet-div-icon {
background: #fff;
border: 1px solid #666;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,99 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Cebu example map</title>
<link rel="shortcut icon" href="http://cartodb.com/favicon/favicon_32x32.ico" />
<link href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="../lib/cartodb.css">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="../lib/wax.g.js"></script>
<script type="text/javascript" src="../lib/cartodb-gmapsv3.js"></script>
<script type="text/javascript" src="../lib/dat.gui.min.js"></script>
<script type="text/javascript" src="../lib/underscore-min.js"></script>
<script type="text/javascript" src="../lib/backbone.js"></script>
<script type="text/javascript" src="../lib/class.js"></script>
<script type="text/javascript" src="../lib/backbone.cartodb.js"></script>
<script type="text/javascript" src="../src/canvas_tile_layer.js"></script>
<script type="text/javascript" src="../src/grid_layer.js"></script>
<script type="text/javascript" src="../src/torque.js"></script>
<script type="text/javascript">
var gui;
function initialize() {
// initialise the google map
var map = new google.maps.Map(document.getElementById('map_canvas'), {
center: new google.maps.LatLng(30,0),
zoom: 2,
mapTypeId:google.maps.MapTypeId.SATELLITE,
mapTypeControl:false,
minZoom:1,
scrollwheel: false,
panControl: false,
zoomControl: false,
scaleControl: false,
streetViewControl: false,
overviewMapControl: false,
});
var map_style = {};
map_style.google_maps_customization_style = [
{
stylers:[
{ invert_lightness:true },
{ weight:1 },
{ saturation:-100 },
{ lightness:-40 }
]
},
{
elementType:"labels",
stylers:[
{ visibility:"simplified" }
]
}
];
var Soft = function () {
this.Soft = function () {
map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
map.setOptions({styles:map_style.google_maps_customization_style});
}
}
map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
map.setOptions({styles:map_style.google_maps_customization_style});
var TorqueOptions = {
user: "simonrogers",
table: "wimblegeov3",
column: "date_utc",
cumulative: false,
resolution: 2,
steps: 750,
fps: 24,
fitbounds: false,
clock: false,
blendmode: 'lighter',
trails: true,
point_type:'circle'
}
var torque = null;
Torque(function (env) {
Torque.app = new env.app.Instance();
torque = new Torque.app.addLayer(map, TorqueOptions);
Torque.env = env;
});
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas"></div>
<div class="torque_time"></div>
<a class="cartodb_logo" href="http://www.cartodb.com" target="_blank">CartoDB</a>
</body>
</html>

28
lib/header.js Normal file
View File

@ -0,0 +1,28 @@
// Adds version header to distributions
var fs = require('fs');
var packageJSON = require('../package.json');
var headerString = ['/**',
'Torque {{version}}',
'{{description}}',
'{{url}}',
'**/\n\n',
'{{lib}}'].join('\n');
headerString = headerString.replace("{{version}}", packageJSON.version)
.replace("{{description}}", packageJSON.description)
.replace("{{url}}", "https://github.com/cartodb/torque");
['torque.uncompressed.js'].forEach(function(v){
fs.readFile('dist/' + v, 'utf8', function(err, torque) {
if (err) {
return console.error(err);
}
var torqueString = headerString.replace("{{lib}}", torque);
fs.writeFile('dist/' + v, torqueString, function (err) {
if (err) {
return console.error(err);
}
});
});
});

View 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;

View File

@ -1,4 +1,5 @@
var torque = require('./'); var torque = require('./');
var AnimatorStepsRange = require('./animator-steps-range');
var requestAnimationFrame = global.requestAnimationFrame var requestAnimationFrame = global.requestAnimationFrame
|| global.mozRequestAnimationFrame || global.mozRequestAnimationFrame
@ -27,6 +28,7 @@ var cancelAnimationFrame = global.cancelAnimationFrame
this._t0 = +new Date(); this._t0 = +new Date();
this.callback = callback; this.callback = callback;
this._time = 0.0; this._time = 0.0;
this.itemsReady = false;
this.options = torque.extend({ this.options = torque.extend({
animationDelay: 0, animationDelay: 0,
@ -34,17 +36,18 @@ var cancelAnimationFrame = global.cancelAnimationFrame
loop: options.loop === undefined ? true : options.loop loop: options.loop === undefined ? true : options.loop
}, this.options); }, this.options);
this.rescale(); this.steps(options.steps);
} }
Animator.prototype = { Animator.prototype = {
start: function() { start: function() {
this.running = true; this.running = true;
requestAnimationFrame(this._tick); requestAnimationFrame(this._tick);
this.options.onStart && this.options.onStart(); this.options.onStart && this.options.onStart();
if (this.stepsRange().diff() === 1) {
this.running = false;
}
}, },
isRunning: function() { isRunning: function() {
@ -53,7 +56,7 @@ var cancelAnimationFrame = global.cancelAnimationFrame
stop: function() { stop: function() {
this.pause(); this.pause();
this.time(0); this.time(this.stepsRange().start);
this.options.onStop && this.options.onStop(); this.options.onStop && this.options.onStop();
}, },
@ -76,9 +79,10 @@ var cancelAnimationFrame = global.cancelAnimationFrame
rescale: function() { rescale: function() {
this.domainInv = torque.math.linear(this.options.animationDelay, this.options.animationDelay + this.options.animationDuration); this.domainInv = torque.math.linear(this.options.animationDelay, this.options.animationDelay + this.options.animationDuration);
this.domain = this.domainInv.invert(); 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.rangeInv = this.range.invert();
this.time(this._time); this.time(this._time);
this.running? this.start(): this.pause();
return this; return this;
}, },
@ -94,9 +98,34 @@ var cancelAnimationFrame = global.cancelAnimationFrame
steps: function(_) { steps: function(_) {
this.options.steps = _; this.options.steps = _;
this._defaultStepsRange = new AnimatorStepsRange(0, _);
return this.rescale(); 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 AnimatorStepsRange(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) { step: function(s) {
if(arguments.length === 0) return this.range(this.domain(this._time)); if(arguments.length === 0) return this.range(this.domain(this._time));
this._time = this.domainInv(this.rangeInv(s)); this._time = this.domainInv(this.rangeInv(s));
@ -116,10 +145,15 @@ var cancelAnimationFrame = global.cancelAnimationFrame
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;
if(this.step() >= this.options.steps) {
this._time = 0; var stepsRange = this.stepsRange();
if (stepsRange.isLast(this.step())) {
if(!this.options.loop){ if(!this.options.loop){
this.stop(); // set time to max time
this.time(this.options.animationDuration);
this.pause();
} else {
this.step(stepsRange.start);
} }
} }
if(this.running) { if(this.running) {

View File

@ -232,6 +232,12 @@ var _torque_reference_latest = {
], ],
"default-value": "ellipse", "default-value": "ellipse",
"doc": "The default marker-type. If a SVG file is not given as the marker-file parameter, the renderer provides either an rectangle or an ellipse (a circle if height is equal to width)" "doc": "The default marker-type. If a SVG file is not given as the marker-file parameter, the renderer provides either an rectangle or an ellipse (a circle if height is equal to width)"
},
"width": {
"css": "marker-width",
"default-value": 10,
"doc": "The width of the marker, if using one of the default types.",
"type": "float"
} }
}, },
"point": { "point": {

View File

@ -61,7 +61,9 @@
// types // types
var types = { var types = {
Uint8Array: typeof(global['Uint8Array']) !== 'undefined' ? global.Uint8Array : Array, Uint8Array: typeof(global['Uint8Array']) !== 'undefined' ? global.Uint8Array : Array,
Uint8ClampedArray: typeof(global['Uint8ClampedArray']) !== 'undefined' ? global.Uint8ClampedArray: Array,
Uint32Array: typeof(global['Uint32Array']) !== 'undefined' ? global.Uint32Array : Array, Uint32Array: typeof(global['Uint32Array']) !== 'undefined' ? global.Uint32Array : Array,
Int16Array: typeof(global['Int16Array']) !== 'undefined' ? global.Int16Array : Array,
Int32Array: typeof(global['Int32Array']) !== 'undefined' ? global.Int32Array: Array Int32Array: typeof(global['Int32Array']) !== 'undefined' ? global.Int32Array: Array
}; };
@ -74,7 +76,7 @@
} }
var flags = { var flags = {
sprites_to_images: userAgent().indexOf('Safari') === -1 sprites_to_images: userAgent().indexOf('Safari') === -1 && userAgent().indexOf('Firefox') === -1
}; };
module.exports = { module.exports = {

View File

@ -287,6 +287,24 @@ CanvasLayer.prototype.setPaneName = function(paneName) {
this.setPane_(); this.setPane_();
}; };
/**
* Set the opacity for the canvas.
*
* @param {number} opacity The opacity of the canvas
*/
CanvasLayer.prototype.setOpacity = function (opacity) {
this.canvas.style.opacity = opacity;
};
/**
* Get the canvases opacity.
*
* @return {number} The opacity of the canvas
*/
CanvasLayer.prototype.getOpacity = function () {
return this.canvas.style.opacity;
};
/** /**
* @return {string} The name of the current container pane. * @return {string} The name of the current container pane.
*/ */

View File

@ -21,16 +21,17 @@ GMapsTileLoader.prototype = {
}, },
_removeTileLoader: function() { _removeTileLoader: function() {
for(var i in this._listeners) { this._listeners.forEach(function (listener) {
google.maps.event.removeListener(this._listeners[i]); google.maps.event.removeListener(listener);
} });
this._removeTiles(); this._removeTiles();
}, },
_removeTiles: function () { _removeTiles: function () {
for (var key in this._tiles) { for (var key in this._tiles) {
this._removeTile(key); this._removeTile(key);
} }
}, },
_reloadTiles: function() { _reloadTiles: function() {

View File

@ -9,7 +9,12 @@ function GMapsTorqueLayer(options) {
if (!torque.isBrowserSupported()) { if (!torque.isBrowserSupported()) {
throw new Error("browser is not supported by torque"); throw new Error("browser is not supported by torque");
} }
this.key = 0; this.keys = [0];
Object.defineProperty(this, 'key', {
get: function() {
return this.getKey();
}
});
this.shader = null; this.shader = null;
this.ready = false; this.ready = false;
this.options = torque.extend({}, options); this.options = torque.extend({}, options);
@ -25,14 +30,31 @@ function GMapsTorqueLayer(options) {
torque.common.TorqueLayer.optionsFromCartoCSS(options.cartocss)); torque.common.TorqueLayer.optionsFromCartoCSS(options.cartocss));
} }
if(options.tileJSON) this.options.provider = "tileJSON";
this.hidden = !this.options.visible; this.hidden = !this.options.visible;
this.showLimitErrors = options.showLimitErrors;
this.animator = new torque.Animator(function(time) { this.animator = new torque.Animator(function(time) {
var k = time | 0; var k = time | 0;
if(self.key !== k) { if(self.getKey() !== k) {
self.setKey(k); self.setKey(k);
} }
}, torque.clone(this.options)); }, torque.extend(torque.clone(this.options), {
onPause: function() {
self.fire('pause');
},
onStop: function() {
self.fire('stop');
},
onStart: function() {
self.fire('play');
},
onStepsRange: function() {
self.fire('change:stepsRange', self.animator.stepsRange());
}
}));
this.play = this.animator.start.bind(this.animator); this.play = this.animator.start.bind(this.animator);
this.stop = this.animator.stop.bind(this.animator); this.stop = this.animator.stop.bind(this.animator);
@ -43,8 +65,6 @@ function GMapsTorqueLayer(options) {
CanvasLayer.call(this, { CanvasLayer.call(this, {
map: this.options.map,
//resizeHandler: this.redraw,
animate: false, animate: false,
updateHandler: this.render, updateHandler: this.render,
readyHandler: this.initialize readyHandler: this.initialize
@ -63,8 +83,9 @@ GMapsTorqueLayer.prototype = torque.extend({},
providers: { providers: {
'sql_api': torque.providers.json, 'sql_api': torque.providers.json,
'url_template': torque.providers.jsonarray, 'url_template': torque.providers.JsonArray,
'windshaft': torque.providers.windshaft 'windshaft': torque.providers.windshaft,
'tileJSON': torque.providers.tileJSON
}, },
renderers: { renderers: {
@ -86,18 +107,19 @@ GMapsTorqueLayer.prototype = torque.extend({},
self.fire('change:steps', { self.fire('change:steps', {
steps: self.provider.getSteps() steps: self.provider.getSteps()
}); });
self.setKey(self.key); self.setKeys(self.getKeys());
}; };
this.provider = new this.providers[this.options.provider](this.options); this.provider = new this.providers[this.options.provider](this.options);
this.renderer = new this.renderers[this.options.renderer](this.getCanvas(), this.options); this.renderer = new this.renderers[this.options.renderer](this.getCanvas(), this.options);
this.renderer.options.errorCallback = this.options.errorCallback;
// this listener should be before tile loader // this listener should be before tile loader
this._cacheListener = google.maps.event.addListener(this.options.map, 'zoom_changed', function() { this._cacheListener = google.maps.event.addListener(this.map, 'zoom_changed', function() {
self.renderer && self.renderer.clearSpriteCache(); self.renderer && self.renderer.clearSpriteCache();
}); });
this._initTileLoader(this.options.map, this.getProjection()); this._initTileLoader(this.map, this.getProjection());
if (this.shader) { if (this.shader) {
this.renderer.setShader(this.shader); this.renderer.setShader(this.shader);
@ -117,10 +139,14 @@ GMapsTorqueLayer.prototype = torque.extend({},
if(!this.hidden) return this; if(!this.hidden) return this;
this.hidden = false; this.hidden = false;
this.play(); this.play();
if (this.options.steps === 1){
this.redraw();
}
return this; return this;
}, },
setSQL: function(sql) { setSQL: function(sql) {
if (this.provider.options.named_map) throw new Error("SQL queries on named maps are read-only");
if (!this.provider || !this.provider.setSQL) { if (!this.provider || !this.provider.setSQL) {
throw new Error("this provider does not support SQL"); throw new Error("this provider does not support SQL");
} }
@ -156,14 +182,24 @@ GMapsTorqueLayer.prototype = torque.extend({},
// for each tile shown on the map request the data // for each tile shown on the map request the data
onTileAdded: function(t) { onTileAdded: function(t) {
var self = this; var self = this;
this.provider.getTileData(t, t.zoom, function(tileData) { var callback = function (tileData, error) {
// don't load tiles that are not being shown // don't load tiles that are not being shown
if (t.zoom !== self.options.map.getZoom()) return; if (t.zoom !== self.map.getZoom()) return;
self._tileLoaded(t, tileData); self._tileLoaded(t, tileData);
if (tileData) { if (tileData) {
self.redraw(); self.redraw();
} }
});
self.fire('tileLoaded');
if (error) {
self.fire('tileError', error);
}
}
this.provider.getTileData(t, t.zoom, callback);
}, },
clear: function() { clear: function() {
@ -189,9 +225,10 @@ GMapsTorqueLayer.prototype = torque.extend({},
if (tile) { if (tile) {
pos = this.getTilePos(tile.coord); pos = this.getTilePos(tile.coord);
ctx.setTransform(1, 0, 0, 1, pos.x, pos.y); ctx.setTransform(1, 0, 0, 1, pos.x, pos.y);
this.renderer.renderTile(tile, this.key, pos.x, pos.y); this.renderer.renderTile(tile, this.keys);
} }
} }
this.renderer.applyFilters();
}, },
getActivePointsBBox: function(step) { getActivePointsBBox: function(step) {
@ -210,14 +247,29 @@ GMapsTorqueLayer.prototype = torque.extend({},
* accumulated * accumulated
*/ */
setKey: function(key) { setKey: function(key) {
this.key = key; this.setKeys([key]);
this.animator.step(key);
this.redraw();
this.fire('change:time', { time: this.getTime(), step: this.key });
}, },
/** /**
* helper function, does the same than ``setKey`` but only * returns the array of keys being rendered
*/
getKeys: function() {
return this.keys;
},
setKeys: function(keys) {
this.keys = keys;
this.animator.step(this.getKey());
this.redraw();
this.fire('change:time', { time: this.getTime(), step: this.getKey() });
},
getKey: function() {
return this.keys[0];
},
/**
* helper function, does the same than ``setKey`` but only
* accepts scalars. * accepts scalars.
*/ */
setStep: function(time) { setStep: function(time) {
@ -227,11 +279,25 @@ GMapsTorqueLayer.prototype = torque.extend({},
this.setKey(time); this.setKey(time);
}, },
renderRange: function(start, end) {
this.pause();
var keys = [];
for (var i = start; i <= end; i++) {
keys.push(i);
}
this.setKeys(keys);
},
resetRenderRange: function() {
this.stop();
this.play();
},
/** /**
* transform from animation step to Date object * transform from animation step to Date object
* that contains the animation time * that contains the animation time
* *
* ``step`` should be between 0 and ``steps - 1`` * ``step`` should be between 0 and ``steps - 1``
*/ */
stepToTime: function(step) { stepToTime: function(step) {
if (!this.provider) return 0; if (!this.provider) return 0;
@ -240,8 +306,16 @@ GMapsTorqueLayer.prototype = torque.extend({},
return new Date(time); return new Date(time);
}, },
timeToStep: function(timestamp) {
if (typeof timestamp === "Date") timestamp = timestamp.getTime();
if (!this.provider) return 0;
var times = this.provider.getKeySpan();
var step = (this.provider.getSteps() * (timestamp - times.start)) / (times.end - times.start);
return step;
},
getStep: function() { getStep: function() {
return this.key; return this.getKey();
}, },
/** /**
@ -249,13 +323,20 @@ GMapsTorqueLayer.prototype = torque.extend({},
* in the defined column. Date object * in the defined column. Date object
*/ */
getTime: function() { getTime: function() {
return this.stepToTime(this.key); return this.stepToTime(this.getKey());
}, },
/** /**
* set the cartocss for the current renderer * set the cartocss for the current renderer
*/ */
setCartoCSS: function(cartocss) { setCartoCSS: function(cartocss) {
if (!this.renderer) throw new Error('renderer is not valid');
if (this.provider && this.provider.options.named_map) {
console.log('Torque layer: CartoCSS style on named maps is read-only');
return false;
}
var shader = new carto.RendererJS().render(cartocss); var shader = new carto.RendererJS().render(cartocss);
this.shader = shader; this.shader = shader;
if (this.renderer) { if (this.renderer) {
@ -284,10 +365,81 @@ GMapsTorqueLayer.prototype = torque.extend({},
}, },
onRemove: function() { onRemove: function() {
this.fire('remove');
CanvasLayer.prototype.onRemove.call(this); CanvasLayer.prototype.onRemove.call(this);
this.animator.stop(); this.animator.stop();
this._removeTileLoader(); this._removeTileLoader();
google.maps.event.removeListener(this._cacheListener); google.maps.event.removeListener(this._cacheListener);
},
/**
* return an array with the values for all the pixels active for the step
*/
getValues: function(step) {
var values = [];
step = step === undefined ? this.getKey(): step;
var t, tile;
for(t in this._tiles) {
tile = this._tiles[t];
this.renderer.getValues(tile, step, values);
}
return values;
},
getValueForPos: function(x, y, step) {
step = step === undefined ? this.getKey(): 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;
},
/** return the number of points for a step */
pointCount: function(step) {
var t, tile;
step = step === undefined ? this.key: step;
var c = 0;
for(t in this._tiles) {
tile = this._tiles[t];
if (tile) {
c += tile.timeCount[step];
}
}
return c;
},
getValueForBBox: function(x, y, w, h) {
var xf = x + w, yf = y + h;
var sum = 0;
for(_y = y; y<yf; y+=this.options.resolution){
for(_x = x; x<xf; x+=this.options.resolution){
var thisValue = this.getValueForPos(_x,_y);
if (thisValue){
var bb = thisValue.bbox;
var proj = this.getProjection()
var xy = proj.fromLatLngToContainerPixel(new google.maps.LatLng(bb[1].lat, bb[1].lon));
if(xy.x < xf && xy.y < yf){
sum += thisValue.value;
}
}
}
}
return sum;
},
error: function (callback) {
this.options.errorCallback = callback;
return this;
} }
}); });
@ -314,7 +466,7 @@ GMapsTiledTorqueLayer.prototype = torque.extend({}, CanvasTileLayer.prototype, {
initialize: function(options) { initialize: function(options) {
var self = this; var self = this;
this.key = 0; this.keys = [0];
this.options.renderer = this.options.renderer || 'pixel'; this.options.renderer = this.options.renderer || 'pixel';
this.options.provider = this.options.provider || 'sql_api'; this.options.provider = this.options.provider || 'sql_api';
@ -350,12 +502,12 @@ GMapsTiledTorqueLayer.prototype = torque.extend({}, CanvasTileLayer.prototype, {
this.renderer.setCanvas(canvas); this.renderer.setCanvas(canvas);
var accum = this.renderer.accumulate(tile.data, this.key); var accum = this.renderer.accumulate(tile.data, this.getKey());
this.renderer.renderTileAccum(accum, 0, 0); this.renderer.renderTileAccum(accum, 0, 0);
}, },
setKey: function(key) { setKey: function(key) {
this.key = key; this.keys = [key];
this.redraw(); this.redraw();
}, },
@ -365,6 +517,18 @@ GMapsTiledTorqueLayer.prototype = torque.extend({}, CanvasTileLayer.prototype, {
setCartoCSS: function(cartocss) { setCartoCSS: function(cartocss) {
if (!this.renderer) throw new Error('renderer is not valid'); if (!this.renderer) throw new Error('renderer is not valid');
return this.renderer.setCartoCSS(cartocss); 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();
} }
}); });

View File

@ -15,3 +15,5 @@ var gmaps = require('./gmaps');
module.exports.GMapsTileLoader = gmaps.GMapsTileLoader; module.exports.GMapsTileLoader = gmaps.GMapsTileLoader;
module.exports.GMapsTorqueLayer = gmaps.GMapsTorqueLayer; module.exports.GMapsTorqueLayer = gmaps.GMapsTorqueLayer;
module.exports.GMapsTiledTorqueLayer = gmaps.GMapsTiledTorqueLayer; module.exports.GMapsTiledTorqueLayer = gmaps.GMapsTiledTorqueLayer;
require('./ol');

View File

@ -4,7 +4,7 @@ require('./leaflet_tileloader_mixin');
* full canvas layer implementation for Leaflet * full canvas layer implementation for Leaflet
*/ */
L.CanvasLayer = L.Class.extend({ L.CanvasLayer = L.Layer.extend({
includes: [L.Mixin.Events, L.Mixin.TileLoader], includes: [L.Mixin.Events, L.Mixin.TileLoader],
@ -64,7 +64,7 @@ L.CanvasLayer = L.Class.extend({
this._map = map; this._map = map;
// add container with the canvas to the tile pane // add container with the canvas to the tile pane
// the container is moved in the oposite direction of the // the container is moved in the oposite direction of the
// map pane to keep the canvas always in (0, 0) // map pane to keep the canvas always in (0, 0)
var tilePane = this._map._panes.tilePane; var tilePane = this._map._panes.tilePane;
var _container = L.DomUtil.create('div', 'leaflet-layer'); var _container = L.DomUtil.create('div', 'leaflet-layer');
@ -85,7 +85,7 @@ L.CanvasLayer = L.Class.extend({
}, this); }, this);
map.on({ 'viewreset': this._reset }, this); map.on({ 'viewreset': this._reset }, this);
map.on('move', this.render, this); map.on('move', this.redraw, this);
map.on('resize', this._reset, this); map.on('resize', this._reset, this);
if (this.options.zoomAnimation) { if (this.options.zoomAnimation) {
@ -128,13 +128,13 @@ L.CanvasLayer = L.Class.extend({
var origin = { var origin = {
x: newCenter.x - oldCenter.x + pos.x, x: newCenter.x - oldCenter.x + pos.x,
y: newCenter.y - oldCenter.y + pos.y, y: newCenter.y - oldCenter.y + pos.y
}; };
var bg = back; var bg = back;
var transform = L.DomUtil.TRANSFORM; var transform = L.DomUtil.TRANSFORM;
setTimeout(function() { setTimeout(function() {
bg.style[transform] = L.DomUtil.getTranslateString(origin) + ' scale(' + e.scale + ') '; bg.style[transform] = 'translate(' + origin.x + 'px, ' + origin.y + 'px) scale(' + e.scale + ') ';
}, 0) }, 0)
}, },
@ -161,7 +161,7 @@ L.CanvasLayer = L.Class.extend({
this._container.parentNode.removeChild(this._container); this._container.parentNode.removeChild(this._container);
map.off({ map.off({
'viewreset': this._reset, 'viewreset': this._reset,
'move': this._render, 'move': this.redraw,
'moveend': this._reset, 'moveend': this._reset,
'resize': this._reset, 'resize': this._reset,
'zoomanim': this._animateZoom, 'zoomanim': this._animateZoom,
@ -174,6 +174,11 @@ L.CanvasLayer = L.Class.extend({
return this; return this;
}, },
error: function (callback) {
this.provider.options.errorCallback = callback;
return this;
},
setOpacity: function (opacity) { setOpacity: function (opacity) {
this.options.opacity = opacity; this.options.opacity = opacity;
this._updateOpacity(); this._updateOpacity();
@ -181,6 +186,8 @@ L.CanvasLayer = L.Class.extend({
}, },
setZIndex: function(zIndex) { setZIndex: function(zIndex) {
zIndex = zIndex !== void 0 ? zIndex : 1;
this._container.style.zIndex = zIndex;
this._canvas.style.zIndex = zIndex; this._canvas.style.zIndex = zIndex;
if (this.options.zoomAnimation) { if (this.options.zoomAnimation) {
this._backCanvas.style.zIndex = zIndex; this._backCanvas.style.zIndex = zIndex;
@ -227,6 +234,10 @@ L.CanvasLayer = L.Class.extend({
// use direct: true if you are inside an animation frame call // use direct: true if you are inside an animation frame call
redraw: function(direct) { redraw: function(direct) {
var domPosition = L.DomUtil.getPosition(this._map.getPanes().mapPane);
if (domPosition) {
L.DomUtil.setPosition(this._canvas, { x: -domPosition.x, y: -domPosition.y });
}
if (direct) { if (direct) {
this.render(); this.render();
} else { } else {

View File

@ -1,7 +1,6 @@
L.Mixin.TileLoader = { L.Mixin.TileLoader = {
_initTileLoader: function() { _initTileLoader: function() {
this._tiles = {}
this._tilesLoading = {}; this._tilesLoading = {};
this._tilesToLoad = 0; this._tilesToLoad = 0;
this._map.on({ this._map.on({
@ -100,7 +99,7 @@ L.Mixin.TileLoader = {
getTilePos: function (tilePoint) { getTilePos: function (tilePoint) {
tilePoint = new L.Point(tilePoint.x, tilePoint.y); tilePoint = new L.Point(tilePoint.x, tilePoint.y);
var origin = this._map._getNewTopLeftPoint(this._map.getCenter()), var origin = this._map._getTopLeftPoint(this._map.getCenter()),
tileSize = this.options.tileSize; tileSize = this.options.tileSize;
return tilePoint.multiplyBy(tileSize).subtract(origin); return tilePoint.multiplyBy(tileSize).subtract(origin);
@ -111,6 +110,8 @@ L.Mixin.TileLoader = {
center = bounds.getCenter(), center = bounds.getCenter(),
zoom = this._map.getZoom(); zoom = this._map.getZoom();
zoom = Math.round(zoom);
var j, i, point; var j, i, point;
for (j = bounds.min.y; j <= bounds.max.y; j++) { for (j = bounds.min.y; j <= bounds.max.y; j++) {
@ -144,4 +145,5 @@ L.Mixin.TileLoader = {
this.fire("tilesLoading"); this.fire("tilesLoading");
} }
} }

View File

@ -10,8 +10,9 @@ 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,
'windshaft': torque.providers.windshaft 'windshaft': torque.providers.windshaft,
'tileJSON': torque.providers.tileJSON
}, },
renderers: { renderers: {
@ -25,10 +26,18 @@ L.TorqueLayer = L.CanvasLayer.extend({
throw new Error("browser is not supported by torque"); throw new Error("browser is not supported by torque");
} }
options.tileLoader = true; options.tileLoader = true;
this.key = 0; this.keys = [0];
this._tiles = {};
Object.defineProperty(this, 'key', {
get: function() {
return this.getKey();
}
});
this.prevRenderedKey = 0; this.prevRenderedKey = 0;
if (options.cartocss) { if (options.cartocss) {
torque.extend(options, torque.common.TorqueLayer.optionsFromCartoCSS(options.cartocss)); // We're only passing the Map header to the global options because the parser won't like turbocarto expressions
var headerCartoCSS = options.cartocss.replace(/\n/g,'').match(/Map\s*?\{.*?}/g)[0];
torque.extend(options, torque.common.TorqueLayer.optionsFromCartoCSS(headerCartoCSS));
} }
options.resolution = options.resolution || 2; options.resolution = options.resolution || 2;
@ -38,7 +47,7 @@ L.TorqueLayer = L.CanvasLayer.extend({
this.animator = new torque.Animator(function(time) { this.animator = new torque.Animator(function(time) {
var k = time | 0; var k = time | 0;
if(self.key !== k) { if(self.getKey() !== k) {
self.setKey(k, { direct: true }); self.setKey(k, { direct: true });
} }
}, torque.extend(torque.clone(options), { }, torque.extend(torque.clone(options), {
@ -50,6 +59,9 @@ L.TorqueLayer = L.CanvasLayer.extend({
}, },
onStart: function() { onStart: function() {
self.fire('play'); self.fire('play');
},
onStepsRange: function() {
self.fire('change:stepsRange', self.animator.stepsRange());
} }
})); }));
@ -60,12 +72,20 @@ L.TorqueLayer = L.CanvasLayer.extend({
this.setDuration = this.animator.duration.bind(this.animator); this.setDuration = this.animator.duration.bind(this.animator);
this.isRunning = this.animator.isRunning.bind(this.animator); this.isRunning = this.animator.isRunning.bind(this.animator);
L.CanvasLayer.prototype.initialize.call(this, options); L.CanvasLayer.prototype.initialize.call(this, options);
this.options.renderer = this.options.renderer || 'point'; this.options.renderer = this.options.renderer || 'point';
this.options.provider = this.options.provider || 'windshaft'; this.options.provider = this.options.provider || 'windshaft';
if (this.options.tileJSON) this.options.provider = 'tileJSON';
this.showLimitErrors = options.showLimitErrors;
this.provider = new this.providers[this.options.provider](options);
options.layer = this;
this.renderer = new this.renderers[this.options.renderer](this.getCanvas(), options);
options.ready = function() { options.ready = function() {
self.fire("change:bounds", { self.fire("change:bounds", {
bounds: self.provider.getBounds() bounds: self.provider.getBounds()
@ -75,27 +95,37 @@ L.TorqueLayer = L.CanvasLayer.extend({
self.fire('change:steps', { self.fire('change:steps', {
steps: self.provider.getSteps() steps: self.provider.getSteps()
}); });
self.setKey(self.key); self.setKeys(self.getKeys());
}; };
this.provider = new this.providers[this.options.provider](options); this.on('tileLoaded', function () {
this.renderer = new this.renderers[this.options.renderer](this.getCanvas(), options); self.renderer.setCartoCSS(self.renderer.style);
})
this.renderer.on("allIconsLoaded", this.render.bind(this));
// for each tile shown on the map request the data // for each tile shown on the map request the data
this.on('tileAdded', function(t) { this.on('tileAdded', function(t) {
var tileData = this.provider.getTileData(t, t.zoom, function(tileData) { var callback = function (tileData, error) {
// don't load tiles that are not being shown // don't load tiles that are not being shown
if (t.zoom !== self._map.getZoom()) return; if (t.zoom !== self._map.getZoom()) return;
self._tileLoaded(t, tileData); self._tileLoaded(t, tileData);
self._clearTileCaches(); self._clearTileCaches();
if (tileData) { if (tileData) {
self.redraw(); self.redraw();
} }
});
self.fire('tileLoaded');
if (error) {
self.fire('tileError', error);
}
};
var tileData = this.provider.getTileData(t, t.zoom, callback);
}, this); }, this);
}, },
_clearTileCaches: function() { _clearTileCaches: function() {
@ -116,7 +146,7 @@ L.TorqueLayer = L.CanvasLayer.extend({
onAdd: function (map) { onAdd: function (map) {
map.on({ map.on({
'zoomend': this._clearCaches, 'zoomend': this._clearCaches,
'zoomstart': this._pauseOnZoom, 'zoomstart': this._pauseOnZoom
}, this); }, this);
map.on({ map.on({
@ -126,10 +156,11 @@ L.TorqueLayer = L.CanvasLayer.extend({
}, },
onRemove: function(map) { onRemove: function(map) {
this.fire('remove');
this._removeTileLoader(); this._removeTileLoader();
map.off({ map.off({
'zoomend': this._clearCaches, 'zoomend': this._clearCaches,
'zoomstart': this._pauseOnZoom, 'zoomstart': this._pauseOnZoom
}, this); }, this);
map.off({ map.off({
'zoomend': this._resumeOnZoom 'zoomend': this._resumeOnZoom
@ -162,10 +193,14 @@ L.TorqueLayer = L.CanvasLayer.extend({
if(!this.hidden) return this; if(!this.hidden) return this;
this.hidden = false; this.hidden = false;
this.play(); this.play();
if (this.options.steps === 1){
this.redraw();
}
return this; return this;
}, },
setSQL: function(sql) { setSQL: function(sql) {
if (this.provider.options.named_map) throw new Error("SQL queries on named maps are read-only");
if (!this.provider || !this.provider.setSQL) { if (!this.provider || !this.provider.setSQL) {
throw new Error("this provider does not support SQL"); throw new Error("this provider does not support SQL");
} }
@ -226,16 +261,16 @@ L.TorqueLayer = L.CanvasLayer.extend({
// all the points // all the points
this.renderer._ctx.drawImage(tile._tileCache, 0, 0); this.renderer._ctx.drawImage(tile._tileCache, 0, 0);
} else { } else {
this.renderer.renderTile(tile, this.key, pos); this.renderer.renderTile(tile, this.keys);
} }
} }
} }
this.renderer.flush(); this.renderer.applyFilters();
// prepare caches if the animation is not running // prepare caches if the animation is not running
// don't cache if the key has just changed, this avoids to cache // don't cache if the key has just changed, this avoids to cache
// when the user is dragging, it only cache when the map is still // when the user is dragging, it only cache when the map is still
if (!this.animator.isRunning() && this.key === this.prevRenderedKey) { if (!this.animator.isRunning() && this.getKey() === this.prevRenderedKey) {
var tile_size = this.renderer.TILE_SIZE; var tile_size = this.renderer.TILE_SIZE;
for(t in this._tiles) { for(t in this._tiles) {
tile = this._tiles[t]; tile = this._tiles[t];
@ -255,7 +290,7 @@ L.TorqueLayer = L.CanvasLayer.extend({
} }
} }
this.prevRenderedKey = this.key; this.prevRenderedKey = this.getKey();
}, },
@ -265,15 +300,39 @@ L.TorqueLayer = L.CanvasLayer.extend({
* accumulated * accumulated
*/ */
setKey: function(key, options) { setKey: function(key, options) {
this.key = key; this.setKeys([key], options);
this.animator.step(key);
this._clearTileCaches();
this.redraw(options && options.direct);
this.fire('change:time', { time: this.getTime(), step: this.key });
}, },
/** /**
* helper function, does the same than ``setKey`` but only * returns the array of keys being rendered
*/
getKeys: function() {
return this.keys;
},
setKeys: function(keys, options) {
this.keys = keys;
this.animator.step(this.getKey());
this._clearTileCaches();
this.redraw(options && options.direct);
this.fire('change:time', {
time: this.getTime(),
step: this.getKey(),
start: this.getKey(),
end: this.getLastKey()
});
},
getKey: function() {
return this.keys[0];
},
getLastKey: function() {
return this.keys[this.keys.length - 1];
},
/**
* helper function, does the same than ``setKey`` but only
* accepts scalars. * accepts scalars.
*/ */
setStep: function(time) { setStep: function(time) {
@ -283,11 +342,25 @@ L.TorqueLayer = L.CanvasLayer.extend({
this.setKey(time); this.setKey(time);
}, },
renderRange: function(start, end) {
this.pause();
var keys = [];
for (var i = start; i <= end; i++) {
keys.push(i);
}
this.setKeys(keys);
},
resetRenderRange: function() {
this.stop();
this.play();
},
/** /**
* transform from animation step to Date object * transform from animation step to Date object
* that contains the animation time * that contains the animation time
* *
* ``step`` should be between 0 and ``steps - 1`` * ``step`` should be between 0 and ``steps - 1``
*/ */
stepToTime: function(step) { stepToTime: function(step) {
var times = this.provider.getKeySpan(); var times = this.provider.getKeySpan();
@ -295,8 +368,16 @@ L.TorqueLayer = L.CanvasLayer.extend({
return new Date(time); return new Date(time);
}, },
timeToStep: function(timestamp) {
if (typeof timestamp === "Date") timestamp = timestamp.getTime();
if (!this.provider) return 0;
var times = this.provider.getKeySpan();
var step = (this.provider.getSteps() * (timestamp - times.start)) / (times.end - times.start);
return step;
},
getStep: function() { getStep: function() {
return this.key; return this.getKey();
}, },
/** /**
@ -304,14 +385,14 @@ L.TorqueLayer = L.CanvasLayer.extend({
* in the defined column. Date object * in the defined column. Date object
*/ */
getTime: function() { getTime: function() {
return this.stepToTime(this.key); return this.stepToTime(this.getKey());
}, },
/** /**
* returns an object with the start and end times * returns an object with the start and end times
*/ */
getTimeSpan: function() { getTimeSpan: function() {
var times = this.provider.getKeySpan(); return this.provider.getKeySpan();
}, },
/** /**
@ -319,25 +400,31 @@ L.TorqueLayer = L.CanvasLayer.extend({
*/ */
setCartoCSS: function(cartocss) { setCartoCSS: function(cartocss) {
if (!this.renderer) throw new Error('renderer is not valid'); if (!this.renderer) throw new Error('renderer is not valid');
var shader = new carto.RendererJS().render(cartocss);
this.renderer.setShader(shader);
// provider options if (this.provider && this.provider.options.named_map) {
var options = torque.common.TorqueLayer.optionsFromLayer(shader.findLayer({ name: 'Map' })); console.log('Torque layer: CartoCSS style on named maps is read-only');
this.provider.setCartoCSS && this.provider.setCartoCSS(cartocss); return false;
if(this.provider.setOptions(options)) {
this._reloadTiles();
} }
torque.extend(this.options, options); this.renderer.setCartoCSS(cartocss, function () {
// provider options
var options = torque.common.TorqueLayer.optionsFromLayer(this.renderer._shader.findLayer({ name: 'Map' }));
this.provider.setCartoCSS && this.provider.setCartoCSS(cartocss);
if(this.provider.setOptions(options)) {
this._reloadTiles();
}
// animator options torque.extend(this.options, options);
if (options.animationDuration) {
this.animator.duration(options.animationDuration); // animator options
} if (options.animationDuration) {
this.animator.duration(options.animationDuration);
}
this._clearCaches();
this.redraw();
return this;
}.bind(this));
this.redraw();
return this;
}, },
/** /**
@ -354,11 +441,25 @@ L.TorqueLayer = L.CanvasLayer.extend({
return positions; return positions;
}, },
/**
* return an array with the values for all the pixels active for the step
*/
getValues: function(step) {
var values = [];
step = step === undefined ? this.getKey(): step;
var t, tile;
for(t in this._tiles) {
tile = this._tiles[t];
this.renderer.getValues(tile, step, values);
}
return values;
},
/** /**
* return the value for position relative to map coordinates. null for no value * return the value for position relative to map coordinates. null for no value
*/ */
getValueForPos: function(x, y, step) { getValueForPos: function(x, y, step) {
step = step === undefined ? this.key: step; step = step === undefined ? this.getKey(): step;
var t, tile, pos, value = null, xx, yy; var t, tile, pos, value = null, xx, yy;
for(t in this._tiles) { for(t in this._tiles) {
tile = this._tiles[t]; tile = this._tiles[t];
@ -375,7 +476,56 @@ L.TorqueLayer = L.CanvasLayer.extend({
return null; return null;
}, },
getValueForBBox: function(x, y, w, h) {
var xf = x + w, yf = y + h, _x=x;
var sum = 0;
for(_y = y; _y<yf; _y+=this.options.resolution){
for(_x = x; _x<xf; _x+=this.options.resolution){
var thisValue = this.getValueForPos(_x,_y);
if (thisValue){
var bb = thisValue.bbox;
var xy = this._map.latLngToContainerPoint([bb[1].lat, bb[1].lon]);
if(xy.x < xf && xy.y < yf){
sum += thisValue.value;
}
}
}
}
return sum;
},
/** return the number of points for a step */
pointCount: function(step) {
var t, tile;
step = step === undefined ? this.key: step;
var c = 0;
for(t in this._tiles) {
tile = this._tiles[t];
if (tile) {
c += tile.timeCount[step];
}
}
return c;
},
invalidate: function() { invalidate: function() {
this.provider.reload(); this.provider.reload();
},
setStepsRange: function(start, end) {
this.animator.stepsRange(start, end);
},
removeStepsRange: function() {
this.animator.removeCustomStepsRange();
},
getStepsRange: function() {
return this.animator.stepsRange();
},
onRemove: function(map) {
L.CanvasLayer.prototype.onRemove.apply(this, arguments);
this.animator.stop();
} }
}); });

View File

@ -0,0 +1,131 @@
require('./ol_tileloader_mixin');
ol.CanvasLayer = function(options) {
this.root_ = document.createElement('div');
this.root_.setAttribute('class', 'ol-heatmap-layer');
this.options = {
subdomains: 'abc',
errorTileUrl: '',
attribution: '',
opacity: 1,
tileLoader: false, // installs tile loading events
tileSize: 256
};
options = options || {};
torque.extend(this.options, options);
ol.TileLoader.call(this, this.options.tileSize, this.options.maxZoom);
this.render = this.render.bind(this);
this._canvas = this._createCanvas();
this.root_.appendChild(this._canvas);
this._ctx = this._canvas.getContext('2d');
this.currentAnimationFrame = -1;
this.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
return window.setTimeout(callback, 1000 / 60);
};
this.cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame ||
window.webkitCancelAnimationFrame || window.msCancelAnimationFrame || function (id) {
clearTimeout(id);
};
if(options.map){
this.setMap(options.map);
}
};
ol.inherits(ol.CanvasLayer, ol.TileLoader);
ol.CanvasLayer.prototype.setMap = function(map){
if(this._map){
//remove
this._map.unByKey(this.pointdragKey_);
this._map.unByKey(this.sizeChangedKey_);
this._map.unByKey(this.moveendKey_);
this._map.getView().unByKey(this.centerChanged_);
}
this._map = map;
if(map){
var overlayContainer = this._map.getViewport().getElementsByClassName("ol-overlaycontainer")[0];
overlayContainer.appendChild(this.root_);
this.pointdragKey_ = map.on('pointerdrag', this._render, this);
this.moveendKey_ = map.on("moveend", this._render, this);
this.centerChanged_ = map.getView().on("change:center", this._render, this);
this.sizeChangedKey_ = map.on('change:size', this._reset, this);
if(this.options.tileLoader) {
ol.TileLoader.prototype._initTileLoader.call(this, map);
}
this._reset();
}
};
ol.CanvasLayer.prototype._createCanvas = function() {
var canvas;
canvas = document.createElement('canvas');
canvas.style.position = 'absolute';
canvas.style.top = 0;
canvas.style.left = 0;
canvas.style.pointerEvents = "none";
canvas.style.zIndex = this.options.zIndex || 0;
return canvas;
};
ol.CanvasLayer.prototype._reset = function () {
this._resize();
};
ol.CanvasLayer.prototype._resize = function() {
var size = this._map.getSize();
var width = size[0];
var height = size[1];
var oldWidth = this._canvas.width;
var oldHeight = this._canvas.height;
// resizing may allocate a new back buffer, so do so conservatively
if (oldWidth !== width || oldHeight !== height) {
this._canvas.width = width;
this._canvas.height = height;
this._canvas.style.width = width + 'px';
this._canvas.style.height = height + 'px';
this.root_.style.width = width + 'px';
this.root_.style.height = height + 'px';
this._render();
}
};
ol.CanvasLayer.prototype._render = function() {
if (this.currentAnimationFrame >= 0) {
this.cancelAnimationFrame.call(window, this.currentAnimationFrame);
}
this.currentAnimationFrame = this.requestAnimationFrame.call(window, this.render);
};
ol.CanvasLayer.prototype.getCanvas = function() {
return this._canvas;
};
ol.CanvasLayer.prototype.getAttribution = function() {
return this.options.attribution;
};
ol.CanvasLayer.prototype.draw = function() {
return this._render();
};
ol.CanvasLayer.prototype.redraw = function(direct) {
if (direct) {
this.render();
} else {
this._render();
}
};
module.exports = ol.CanvasLayer;

3
lib/torque/ol/index.js Normal file
View File

@ -0,0 +1,3 @@
if (typeof ol !== 'undefined') {
require('./torque');
}

View File

@ -0,0 +1,169 @@
ol.TileLoader = function(tileSize, maxZoom){
this._tileSize = tileSize;
this._tiles = {};
this._tilesLoading = {};
this._tilesToLoad = 0;
this._updateTiles = this._updateTiles.bind(this);
this._tileGrid = ol.tilegrid.createXYZ({
maxZoom: maxZoom,
tileSize: tileSize
});
};
ol.TileLoader.prototype._initTileLoader = function(map) {
this._map = map;
this._view = map.getView();
this._centerChangedId = this._view.on("change:center", function(e){
this._updateTiles();
}, this);
this._postcomposeKey = undefined;
this._resolutionChangedId = this._view.on("change:resolution", function(evt){
this._currentResolution = this._view.getResolution();
if(this._postcomposeKey) return;
this.fire("mapZoomStart");
this._postcomposeKey = this._map.on("postcompose", function(evt) {
if(evt.frameState.viewState.resolution === this._currentResolution){
this._updateTiles();
this._map.unByKey(this._postcomposeKey);
this._postcomposeKey = undefined;
this.fire("mapZoomEnd");
}
}, this);
}, this);
this._updateTiles();
};
ol.TileLoader.prototype._removeTileLoader = function() {
this._view.unByKey(this._centerChangedId);
this._view.unByKey(this._resolutionChangedId );
this._removeTiles();
};
ol.TileLoader.prototype._removeTiles = function () {
for (var key in this._tiles) {
this._removeTile(key);
}
};
ol.TileLoader.prototype._reloadTiles = function() {
this._removeTiles();
this._updateTiles();
};
ol.TileLoader.prototype._updateTiles = function () {
if (!this._map) { return; }
var zoom = this._tileGrid.getZForResolution(this._view.getResolution());
var extent = this._view.calculateExtent(this._map.getSize());
var tileRange = this._requestTilesForExtentAndZ(extent, zoom);
this._removeOtherTiles(tileRange);
};
ol.TileLoader.prototype._removeOtherTiles = function(tileRange) {
var kArr, x, y, z, key;
var zoom = this._tileGrid.getZForResolution(this._view.getResolution());
for (key in this._tiles) {
if (this._tiles.hasOwnProperty(key)) {
kArr = key.split(':');
x = parseInt(kArr[0], 10);
y = parseInt(kArr[1], 10);
z = parseInt(kArr[2], 10);
// remove tile if it's out of bounds
if (z !== zoom || x < tileRange.minX || x > tileRange.maxX || ((-y-1) < tileRange.minY) || (-y-1) > tileRange.maxY) {
this._removeTile(key);
}
}
}
};
ol.TileLoader.prototype._removeTile = function (key) {
this.fire('tileRemoved', this._tiles[key]);
delete this._tiles[key];
delete this._tilesLoading[key];
};
ol.TileLoader.prototype._tileKey = function(tilePoint) {
return tilePoint.x + ':' + tilePoint.y + ':' + tilePoint.zoom;
};
ol.TileLoader.prototype._tileShouldBeLoaded = function (tilePoint) {
var k = this._tileKey(tilePoint);
return !(k in this._tiles) && !(k in this._tilesLoading);
};
ol.TileLoader.prototype._removeFromTilesLoading = function(tilePoint){
this._tilesToLoad--;
var k = this._tileKey(tilePoint);
delete this._tilesLoading[k];
if(this._tilesToLoad === 0) {
this.fire("tilesLoaded");
}
};
ol.TileLoader.prototype._tileLoaded = function(tilePoint, tileData) {
var k = this._tileKey(tilePoint);
this._tiles[k] = tileData;
};
ol.TileLoader.prototype.getTilePos = function (tilePoint) {
var zoom = this._tileGrid.getZForResolution(this._view.getResolution());
var extent = this._tileGrid.getTileCoordExtent([zoom, tilePoint.x, -tilePoint.y-1]);
var topLeft = this._map.getPixelFromCoordinate([extent[0], extent[3]]);
return {
x: topLeft[0],
y: topLeft[1]
};
};
ol.TileLoader.prototype._requestTilesForExtentAndZ = function (extent, zoom) {
var queue = [];
var tileCoords = [];
this._tileGrid.forEachTileCoord(extent, zoom, function(coord){
tileCoords.push(coord);
var point = {
x: coord[1],
y: -coord[2] - 1,
zoom: coord[0]
};
if (this._tileShouldBeLoaded(point)) {
queue.push(point);
}
}.bind(this));
var tilesToLoad = queue.length;
if (tilesToLoad > 0) {
this._tilesToLoad += tilesToLoad;
for (var i = 0; i < tilesToLoad; i++) {
var t = queue[i];
var k = this._tileKey(t);
this._tilesLoading[k] = t;
// events
this.fire('tileAdded', t);
}
this.fire("tilesLoading");
}
var tileRange = {
minX : tileCoords[0][1],
maxX : tileCoords [tileCoords.length - 1][1],
minY : tileCoords[0][2],
maxY : tileCoords [tileCoords.length - 1] [2]
};
return tileRange;
};
module.exports = ol.TileLoader;

443
lib/torque/ol/torque.js Normal file
View File

@ -0,0 +1,443 @@
var carto = global.carto || require('carto');
var torque = require('../');
require('./canvas_layer');
ol.TorqueLayer = function(options){
var self = this;
if (!torque.isBrowserSupported()) {
throw new Error("browser is not supported by torque");
}
options.tileLoader = true;
this.keys = [0];
Object.defineProperty(this, 'key', {
get: function() {
return this.getKey();
}
});
this.prevRenderedKey = 0;
if (options.cartocss) {
torque.extend(options, torque.common.TorqueLayer.optionsFromCartoCSS(options.cartocss));
}
options.resolution = options.resolution || 2;
options.steps = options.steps || 100;
options.visible = options.visible === undefined ? true: options.visible;
this.hidden = !options.visible;
this.animator = new torque.Animator(function(time) {
var k = time | 0;
if(self.getKey() !== k) {
self.setKey(k, { direct: true });
}
}, torque.extend(torque.clone(options), {
onPause: function() {
self.fire('pause');
},
onStop: function() {
self.fire('stop');
},
onStart: function() {
self.fire('play');
},
onStepsRange: function() {
self.fire('change:stepsRange', self.animator.stepsRange());
}
}));
this.play = this.animator.start.bind(this.animator);
this.stop = this.animator.stop.bind(this.animator);
this.pause = this.animator.pause.bind(this.animator);
this.toggle = this.animator.toggle.bind(this.animator);
this.setDuration = this.animator.duration.bind(this.animator);
this.isRunning = this.animator.isRunning.bind(this.animator);
ol.CanvasLayer.call(this, options);
this.options.renderer = this.options.renderer || 'point';
this.options.provider = this.options.provider || 'windshaft';
if (this.options.tileJSON) this.options.provider = 'tileJSON';
this.provider = new this.providers[this.options.provider](options);
this.renderer = new this.renderers[this.options.renderer](this.getCanvas(), options);
options.ready = function() {
self.fire("change:bounds", {
bounds: self.provider.getBounds()
});
self.animator.steps(self.provider.getSteps());
self.animator.rescale();
self.fire('change:steps', {
steps: self.provider.getSteps()
});
self.setKeys(self.getKeys());
};
this.renderer.on("allIconsLoaded", this.render.bind(this));
// for each tile shown on the map request the data
this.on('tileAdded', function(t) {
var tileData = this.provider.getTileData(t, t.zoom, function(tileData) {
self._removeFromTilesLoading(t);
if (t.zoom !== self._tileGrid.getZForResolution(self._view.getResolution())) return;
self._tileLoaded(t, tileData);
self.fire('tileLoaded');
if (tileData) {
self.redraw();
}
});
}, this);
this.on('mapZoomStart', function(){
this.getCanvas().style.display = "none";
this._pauseOnZoom();
}, this);
this.on('mapZoomEnd', function() {
this.getCanvas().style.display = "block";
this._resumeOnZoom();
}, this);
};
ol.TorqueLayer.prototype = torque.extend({},
ol.CanvasLayer.prototype,
torque.Event,
{
providers: {
'sql_api': torque.providers.json,
'url_template': torque.providers.JsonArray,
'windshaft': torque.providers.windshaft,
'tileJSON': torque.providers.tileJSON
},
renderers: {
'point': torque.renderer.Point,
'pixel': torque.renderer.Rectangle
},
onAdd: function(map){
ol.CanvasLayer.prototype.setMap.call(this, map);
},
onRemove: function(map) {
this.fire('remove');
this._removeTileLoader();
},
_pauseOnZoom: function() {
this.wasRunning = this.isRunning();
if (this.wasRunning) {
this.pause();
}
},
_resumeOnZoom: function() {
if (this.wasRunning) {
this.play();
}
},
hide: function() {
if(this.hidden) return this;
this.pause();
this.clear();
this.hidden = true;
return this;
},
show: function() {
if(!this.hidden) return this;
this.hidden = false;
this.play();
if (this.options.steps === 1){
this.redraw();
}
return this;
},
setSQL: function(sql) {
if (this.provider.options.named_map) throw new Error("SQL queries on named maps are read-only");
if (!this.provider || !this.provider.setSQL) {
throw new Error("this provider does not support SQL");
}
this.provider.setSQL(sql);
this._reloadTiles();
return this;
},
setBlendMode: function(_) {
this.renderer.setBlendMode(_);
this.redraw();
},
setSteps: function(steps) {
this.provider.setSteps(steps);
this._reloadTiles();
},
setColumn: function(column, isTime) {
this.provider.setColumn(column, isTime);
this._reloadTiles();
},
getTimeBounds: function() {
return this.provider && this.provider.getKeySpan();
},
clear: function() {
var canvas = this.getCanvas();
canvas.width = canvas.width;
},
/**
* render the selectef key
* don't call this function directly, it's called by
* requestAnimationFrame. Use redraw to refresh it
*/
render: function() {
if(this.hidden) return;
var t, tile, pos;
var canvas = this.getCanvas();
this.renderer.clearCanvas();
var ctx = canvas.getContext('2d');
// renders only a "frame"
for(t in this._tiles) {
tile = this._tiles[t];
if (tile) {
pos = this.getTilePos(tile.coord);
ctx.setTransform(1, 0, 0, 1, pos.x, pos.y);
this.renderer.renderTile(tile, this.keys);
}
}
this.renderer.applyFilters();
},
/**
* set key to be shown. If it's a single value
* it renders directly, if it's an array it renders
* accumulated
*/
setKey: function(key, options) {
this.setKeys([key], options);
},
/**
* returns the array of keys being rendered
*/
getKeys: function() {
return this.keys;
},
setKeys: function(keys, options) {
this.keys = keys;
this.animator.step(this.getKey());
this.redraw(options && options.direct);
this.fire('change:time', {
time: this.getTime(),
step: this.getKey(),
start: this.getKey(),
end: this.getLastKey()
});
},
getKey: function() {
return this.keys[0];
},
getLastKey: function() {
return this.keys[this.keys.length - 1];
},
/**
* helper function, does the same than ``setKey`` but only
* accepts scalars.
*/
setStep: function(time) {
if(time === undefined || time.length !== undefined) {
throw new Error("setTime only accept scalars");
}
this.setKey(time);
},
renderRange: function(start, end) {
this.pause();
var keys = [];
for (var i = start; i <= end; i++) {
keys.push(i);
}
this.setKeys(keys);
},
resetRenderRange: function() {
this.stop();
this.play();
},
/**
* 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.provider.getSteps());
return new Date(time);
},
timeToStep: function(timestamp) {
if (typeof timestamp === "Date") timestamp = timestamp.getTime();
if (!this.provider) return 0;
var times = this.provider.getKeySpan();
var step = (this.provider.getSteps() * (timestamp - times.start)) / (times.end - times.start);
return step;
},
getStep: function() {
return this.getKey();
},
/**
* returns the animation time defined by the data
* in the defined column. Date object
*/
getTime: function() {
return this.stepToTime(this.getKey());
},
/**
* returns an object with the start and end times
*/
getTimeSpan: function() {
return this.provider.getKeySpan();
},
/**
* set the cartocss for the current renderer
*/
setCartoCSS: function(cartocss) {
if (this.provider.options.named_map) throw new Error("CartoCSS style on named maps is read-only");
if (!this.renderer) throw new Error('renderer is not valid');
var shader = new carto.RendererJS().render(cartocss);
this.renderer.setShader(shader);
// provider options
var options = torque.common.TorqueLayer.optionsFromLayer(shader.findLayer({ name: 'Map' }));
this.provider.setCartoCSS && this.provider.setCartoCSS(cartocss);
if(this.provider.setOptions(options)) {
this._reloadTiles();
}
torque.extend(this.options, options);
// animator options
if (options.animationDuration) {
this.animator.duration(options.animationDuration);
}
this.redraw();
return this;
},
/**
* get active points for a step in active zoom
* returns a list of bounding boxes [[] , [], []]
* empty list if there is no active pixels
*/
getActivePointsBBox: function(step) {
var positions = [];
for(var t in this._tiles) {
var tile = this._tiles[t];
positions = positions.concat(this.renderer.getActivePointsBBox(tile, step));
}
return positions;
},
/**
* return an array with the values for all the pixels active for the step
*/
getValues: function(step) {
var values = [];
step = step === undefined ? this.getKey(): step;
var t, tile;
for(t in this._tiles) {
tile = this._tiles[t];
this.renderer.getValues(tile, step, values);
}
return values;
},
/**
* return the value for position relative to map coordinates. null for no value
*/
getValueForPos: function(x, y, step) {
step = step === undefined ? this.getKey(): 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;
},
getValueForBBox: function(x, y, w, h) {
var xf = x + w, yf = y + h, _x=x;
var sum = 0;
for(_y = y; _y<yf; _y+=this.options.resolution){
for(_x = x; _x<xf; _x+=this.options.resolution){
var thisValue = this.getValueForPos(_x,_y);
if (thisValue){
var bb = thisValue.bbox;
var xy = this._map.latLngToContainerPoint([bb[1].lat, bb[1].lon]);
if(xy.x < xf && xy.y < yf){
sum += thisValue.value;
}
}
}
}
return sum;
},
/** return the number of points for a step */
pointCount: function(step) {
var t, tile;
step = step === undefined ? this.key: step;
var c = 0;
for(t in this._tiles) {
tile = this._tiles[t];
if (tile) {
c += tile.timeCount[step];
}
}
return c;
},
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();
}
});
module.exports = ol.TorqueLayer;

View File

@ -1,5 +1,6 @@
module.exports = { module.exports = {
json: require('./json'), json: require('./json'),
JsonArray: require('./jsonarray'), JsonArray: require('./jsonarray'),
windshaft: require('./windshaft') windshaft: require('./windshaft'),
tileJSON: require('./tilejson')
}; };

View File

@ -472,7 +472,7 @@ var Profiler = require('../profiler');
torque.net.jsonp(url, function (data) { torque.net.jsonp(url, function (data) {
var query = format("select * from ({sql}) __torque_wrap_sql limit 0", { sql: self.getSQL() }); var query = format("select * from ({sql}) __torque_wrap_sql limit 0", { sql: self.getSQL() });
self.sql(query, function (queryData) { self.sql(query, function (queryData) {
if (data) { if (data && queryData) {
callback({ callback({
updated_at: data.last_updated, updated_at: data.last_updated,
fields: queryData.fields fields: queryData.fields

View File

@ -0,0 +1,339 @@
var torque = require('../');
var Uint8Array = torque.types.Uint8Array;
var Int32Array = torque.types.Int32Array;
var Uint32Array = torque.types.Uint32Array;
var Uint8ClampedArray = torque.types.Uint8ClampedArray;
// 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 tileJSON = function (options) {
this._ready = false;
this._tileQueue = [];
this.options = options;
this.options.coordinates_data_type = this.options.coordinates_data_type || Uint8Array;
if (this.options.data_aggregation) {
this.options.cumulative = this.options.data_aggregation === 'cumulative';
}
if (this.options.auth_token) {
var e = this.options.extra_params || (this.options.extra_params = {});
e.auth_token = this.options.auth_token;
}
if (!this.options.no_fetch_map) {
this._fetchMap();
}
};
tileJSON.prototype = {
NAME: "tileJSON",
/**
* 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 this.options.coordinates_data_type(rows.length);
var y = new this.options.coordinates_data_type(rows.length);
// 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: Uint8ClampedArray;
// 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);
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;
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]);
}
}
}
// 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;
}
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
};
},
setSteps: function(steps, opt) {
opt = opt || {};
if (this.options.steps !== steps) {
this.options.steps = steps;
this.options.step = (this.options.end - this.options.start)/this.getSteps();
this.options.step = this.options.step || 1;
if (!opt.silent) this.reload();
}
},
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;
}
if(opt.data_aggregation !== undefined) {
var c = opt.data_aggregation === 'cumulative';
if (this.options.cumulative !== c) {
this.options.cumulative = c;
refresh = true;
}
}
if (refresh) this.reload();
return refresh;
},
_extraParams: function(e) {
e = torque.extend(torque.extend({}, e), this.options.extra_params);
if (e) {
var p = [];
for(var k in e) {
var v = e[k];
if (v) {
if (torque.isArray(v)) {
for (var i = 0, len = v.length; i < len; i++) {
p.push(k + "[]=" + encodeURIComponent(v[i]));
}
} else {
p.push(k + "=" + encodeURIComponent(v));
}
}
}
return p.join('&');
}
return null;
},
getTileData: function(coord, zoom, callback) {
if(!this._ready) {
this._tileQueue.push([coord, zoom, callback]);
} else {
this._getTileData(coord, zoom, callback);
}
},
_setReady: function(ready) {
this._ready = true;
this._processQueue();
this.options.ready && this.options.ready();
},
_processQueue: function() {
var item;
while (item = this._tileQueue.pop()) {
this._getTileData.apply(this, item);
}
},
/**
* `coord` object like {x : tilex, y: tiley }
* `zoom` quadtree zoom level
*/
_getTileData: function(coord, zoom, callback) {
var self = this;
var subdomains = this.options.subdomains || '0123';
var limit_x = Math.pow(2, zoom);
var corrected_x = ((coord.x % limit_x) + limit_x) % limit_x;
var index = Math.abs(corrected_x + coord.y) % subdomains.length;
var extra = this._extraParams();
var url = this.templateUrl
.replace('{x}', corrected_x)
.replace('{y}', coord.y)
.replace('{z}', zoom)
.replace('{s}', subdomains[index])
url += extra;
torque.net.get( url , function (data) {
if (data && data.responseText) {
var rows = JSON.parse(data.responseText);
callback(self.proccessTile(rows, coord, zoom));
} else {
callback(null);
}
});
},
getKeySpan: function() {
return {
start: this.options.start,
end: this.options.end,
step: this.options.step,
steps: this.options.steps,
columnType: this.options.column_type
};
},
setColumn: function(column, isTime) {
this.options.column = column;
this.options.is_time = isTime === undefined ? true: false;
this.reload();
},
reload: function() {
this._ready = false;
this._fetchMap();
},
getSteps: function() {
return Math.min(this.options.steps, this.options.data_steps);
},
getBounds: function() {
return this.options.bounds;
},
getSQL: function() {
return this.options.sql || "select * from " + this.options.table;
},
setSQL: function(sql) {
if (this.options.sql != sql) {
this.options.sql = sql;
this.reload();
}
},
_isUserTemplateUrl: function(t) {
return t && t.indexOf('{user}') !== -1;
},
isHttps: function() {
return this.options.maps_api_template.indexOf('https') === 0;
},
_fetchMap: function(callback) {
var self = this;
torque.net.get(this.options.tileJSON, function (data) {
data = JSON.parse(data.response);
if (data) {
if (data.errors){
self.options.errorCallback && self.options.errorCallback(data.errors);
return;
}
for(var k in data) {
self.options[k] = data[k];
}
self.templateUrl = data.tiles[0];
if (self.templateUrl.indexOf("http") !== 0){
self.templateUrl = self.options.tileJSON.substring(0, self.options.tileJSON.lastIndexOf("/") + 1) + self.templateUrl;
}
self._setReady(true);
}
});
}
};
module.exports = tileJSON;

View File

@ -4,6 +4,7 @@
var Uint8Array = torque.types.Uint8Array; var Uint8Array = torque.types.Uint8Array;
var Int32Array = torque.types.Int32Array; var Int32Array = torque.types.Int32Array;
var Uint32Array = torque.types.Uint32Array; var Uint32Array = torque.types.Uint32Array;
var Uint8ClampedArray = torque.types.Uint8ClampedArray;
// format('hello, {0}', 'rambo') -> "hello, rambo" // format('hello, {0}', 'rambo') -> "hello, rambo"
function format(str) { function format(str) {
@ -16,7 +17,7 @@
return str; return str;
} }
var json = function (options) { var windshaft = function (options) {
this._ready = false; this._ready = false;
this._tileQueue = []; this._tileQueue = [];
this.options = options; this.options = options;
@ -26,6 +27,15 @@
this.options.tiler_domain = options.tiler_domain || 'cartodb.com'; this.options.tiler_domain = options.tiler_domain || 'cartodb.com';
this.options.tiler_port = options.tiler_port || 80; this.options.tiler_port = options.tiler_port || 80;
// backwards compatible
if (!options.maps_api_template) {
this._buildMapsApiTemplate(this.options);
} else {
this.options.maps_api_template = options.maps_api_template;
}
this.options.coordinates_data_type = this.options.coordinates_data_type || Uint8Array;
if (this.options.data_aggregation) { if (this.options.data_aggregation) {
this.options.cumulative = this.options.data_aggregation === 'cumulative'; this.options.cumulative = this.options.data_aggregation === 'cumulative';
} }
@ -33,11 +43,12 @@
var e = this.options.extra_params || (this.options.extra_params = {}); var e = this.options.extra_params || (this.options.extra_params = {});
e.auth_token = this.options.auth_token; e.auth_token = this.options.auth_token;
} }
if (!this.options.no_fetch_map) {
this._fetchMap(); this._fetchMap();
}
}; };
json.prototype = { windshaft.prototype = {
/** /**
* return the torque tile encoded in an efficient javascript * return the torque tile encoded in an efficient javascript
@ -50,8 +61,8 @@
*/ */
proccessTile: function(rows, coord, zoom) { proccessTile: function(rows, coord, zoom) {
var r; var r;
var x = new Uint8Array(rows.length); var x = new this.options.coordinates_data_type(rows.length);
var y = new Uint8Array(rows.length); var y = new this.options.coordinates_data_type(rows.length);
var prof_mem = Profiler.metric('torque.provider.windshaft.mem'); var prof_mem = Profiler.metric('torque.provider.windshaft.mem');
var prof_point_count = Profiler.metric('torque.provider.windshaft.points'); var prof_point_count = Profiler.metric('torque.provider.windshaft.points');
@ -72,7 +83,7 @@
dates = (1 + maxDateSlots) * rows.length; dates = (1 + maxDateSlots) * rows.length;
} }
var type = this.options.cumulative ? Uint32Array: Uint8Array; var type = this.options.cumulative ? Uint32Array: Uint8ClampedArray;
// reserve memory for all the dates // reserve memory for all the dates
var timeIndex = new Int32Array(maxDateSlots + 1); //index-size var timeIndex = new Int32Array(maxDateSlots + 1); //index-size
@ -95,13 +106,7 @@
for (var r = 0; r < rows.length; ++r) { for (var r = 0; r < rows.length; ++r) {
var row = rows[r]; var row = rows[r];
x[r] = row.x__uint8 * this.options.resolution; x[r] = row.x__uint8 * this.options.resolution;
// fix value when it's in the tile EDGE y[r] = row.y__uint8 * this.options.resolution;
// 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 dates = row.dates__uint16;
var vals = row.vals__uint8; var vals = row.vals__uint8;
@ -181,11 +186,22 @@
}; };
}, },
proccessTileError: function(error, coord, zoom) {
return {
error: error,
coord: {
x: coord.x,
y: coord.y,
z: zoom
}
};
},
/*setCartoCSS: function(c) { /*setCartoCSS: function(c) {
this.options.cartocss = c; this.options.cartocss = c;
},*/ },*/
setSteps: function(steps, opt) { setSteps: function(steps, opt) {
opt = opt || {}; opt = opt || {};
if (this.options.steps !== steps) { if (this.options.steps !== steps) {
this.options.steps = steps; this.options.steps = steps;
@ -280,19 +296,28 @@
var self = this; var self = this;
var prof_fetch_time = Profiler.metric('torque.provider.windshaft.tile.fetch').start(); var prof_fetch_time = Profiler.metric('torque.provider.windshaft.tile.fetch').start();
var subdomains = this.options.subdomains || '0123'; var subdomains = this.options.subdomains || '0123';
var index = Math.abs(coord.x + coord.y) % subdomains.length; var limit_x = Math.pow(2, zoom);
var corrected_x = ((coord.x % limit_x) + limit_x) % limit_x;
var index = Math.abs(corrected_x + coord.y) % subdomains.length;
var url = this.templateUrl var url = this.templateUrl
.replace('{x}', coord.x) .replace('{x}', corrected_x)
.replace('{y}', coord.y) .replace('{y}', coord.y)
.replace('{z}', zoom) .replace('{z}', zoom)
.replace('{s}', subdomains[index]) .replace('{s}', subdomains[index])
var extra = this._extraParams(); var extra = this._extraParams();
torque.net.get( url + (extra ? "?" + extra: ''), function (data) { torque.net.get( url + (extra ? "?" + extra: ''), function (response) {
prof_fetch_time.end(); prof_fetch_time.end();
if (data && data.responseText) { if (response && response.responseText) {
var rows = JSON.parse(data.responseText); var body = JSON.parse(response.responseText);
callback(self.proccessTile(rows, coord, zoom));
if (response.status === 429) {
var error = body.errors_with_context[0];
callback(self.proccessTileError(error, coord, zoom), error);
} else {
callback(self.proccessTile(body, coord, zoom));
}
} else { } else {
Profiler.metric('torque.provider.windshaft.tile.error').inc(); Profiler.metric('torque.provider.windshaft.tile.error').inc();
callback(null); callback(null);
@ -340,31 +365,53 @@
} }
}, },
_tilerHost: function() { _buildMapsApiTemplate: function(opts) {
var opts = this.options; var user = opts.user_name || opts.user;
var user = (opts.user_name || opts.user); opts.maps_api_template = opts.tiler_protocol +
return opts.tiler_protocol + "://" + ((user) ? "{user}.":"") +
"://" + (user ? user + "." : "") +
opts.tiler_domain + opts.tiler_domain +
((opts.tiler_port != "") ? (":" + opts.tiler_port) : ""); ((opts.tiler_port != "") ? (":" + opts.tiler_port) : "");
}, },
url: function() { _tilerHost: function() {
var opts = this.options;
var user = opts.user_name || opts.user;
return opts.maps_api_template.replace('{user}', user);
},
url: function () {
var opts = this.options; var opts = this.options;
var protocol = opts.tiler_protocol || 'http';
if (!this.options.cdn_url || this.options.no_cdn) {
return this._tilerHost();
}
var h = protocol + "://"
if (protocol === 'http') {
h += "{s}.";
}
var cdn_host = opts.cdn_url; var cdn_host = opts.cdn_url;
if(!cdn_host.http && !cdn_host.https) { var has_empty_cdn = !cdn_host || (cdn_host && (!cdn_host.http && !cdn_host.https));
throw new Error("cdn_host should contain http and/or https entries");
if (opts.no_cdn || has_empty_cdn) {
return this._tilerHost();
} else {
var protocol = this.isHttps() ? 'https': 'http';
var h = protocol + "://";
if (!this.isHttps()) {
h += "{s}.";
}
var cdn_url = cdn_host[protocol];
// build default template url if the cdn url is not templatized
// this is for backwards compatiblity, ideally we should use the url
// that tiler sends to us right away
if (!this._isUserTemplateUrl(cdn_url)) {
cdn_url = cdn_url + "/{user}";
}
var user = opts.user_name || opts.user;
h += cdn_url.replace('{user}', user)
return h;
} }
h += cdn_host[protocol] + "/" + (opts.user_name || opts.user);
return h; },
_isUserTemplateUrl: function(t) {
return t && t.indexOf('{user}') !== -1;
},
isHttps: function() {
return this.options.maps_api_template.indexOf('https') === 0;
}, },
_generateCartoCSS: function() { _generateCartoCSS: function() {
@ -388,10 +435,14 @@
var host = this.options.dynamic_cdn ? this.url().replace('{s}', '0'): this._tilerHost(); var host = this.options.dynamic_cdn ? this.url().replace('{s}', '0'): this._tilerHost();
var url = host + "/api/v1/map"; var url = host + "/api/v1/map";
var named = this.options.named_map; var named = this.options.named_map;
var allParams = {};
if(named) { if(named) {
//tiles/template //tiles/template
url = host + "/api/v1/map/named/" + named.name + "/jsonp"; url = host + "/api/v1/map/named/" + named.name + "/jsonp";
if(typeof named.params !== "undefined"){
layergroup = named.params;
}
} else { } else {
layergroup = { layergroup = {
"version": "1.0.1", "version": "1.0.1",
@ -406,7 +457,12 @@
}] }]
}; };
} }
var extra = this._extraParams(this.options.stat_tag ? { stat_tag: this.options.stat_tag }: {} );
if(this.options.stat_tag){
allParams["stat_tag"] = this.options.stat_tag;
}
extra = this._extraParams(allParams);
// tiler needs map_key instead of api_key // tiler needs map_key instead of api_key
// so replace it // so replace it
@ -422,6 +478,10 @@
torque.net.jsonp(url, function (data) { torque.net.jsonp(url, function (data) {
map_instance_time.end(); map_instance_time.end();
if (data) { if (data) {
if (data.errors){
self.options.errorCallback && self.options.errorCallback(data.errors);
return;
}
var torque_key = Object.keys(data.metadata.torque)[0] var torque_key = Object.keys(data.metadata.torque)[0]
var opt = data.metadata.torque[torque_key]; var opt = data.metadata.torque[torque_key];
for(var k in opt) { for(var k in opt) {
@ -443,4 +503,4 @@
}; };
module.exports = json; module.exports = windshaft;

View File

@ -2,34 +2,38 @@
// min value to render a line. // min value to render a line.
// it does not make sense to render a line of a width is not even visible // it does not make sense to render a line of a width is not even visible
var LINEWIDTH_MIN_VALUE = 0.05; var LINEWIDTH_MIN_VALUE = 0.05;
var MAX_SPRITE_RADIUS = 255;
function renderPoint(ctx, st) { function renderPoint(ctx, st) {
ctx.fillStyle = st['marker-fill']; ctx.fillStyle = st['marker-fill'];
var pixel_size = st['marker-width']; var pixel_size = st['marker-width'];
// render a circle // render a circle
// TODO: fill and stroke order should depend on the order of the properties
// in the cartocss.
// fill // fill
ctx.beginPath(); ctx.beginPath();
ctx.arc(0, 0, pixel_size, 0, TAU, true, true); ctx.arc(0, 0, pixel_size, 0, TAU, true, true);
ctx.closePath(); ctx.closePath();
if (st['marker-opacity'] !== undefined ) st['marker-fill-opacity'] = st['marker-line-opacity'] = st['marker-opacity'];
if (st['marker-fill']) { if (st['marker-fill']) {
if (st['marker-fill-opacity'] !== undefined || st['marker-opacity'] !== undefined) { ctx.globalAlpha = st['marker-fill-opacity'] >= 0? st['marker-fill-opacity']: 1;
ctx.globalAlpha = st['marker-fill-opacity'] || st['marker-opacity'];
if (ctx.globalAlpha > 0) {
ctx.fill();
} }
ctx.fill();
} }
// stroke // stroke
ctx.globalAlpha = 1.0; if (st['marker-line-color'] && st['marker-line-width'] && st['marker-line-width'] > LINEWIDTH_MIN_VALUE) {
if (st['line-color'] && st['line-width'] && st['line-width'] > LINEWIDTH_MIN_VALUE) { ctx.globalAlpha = st['marker-line-opacity'] >= 0? st['marker-line-opacity']: 1;
if (st['marker-line-opacity']) { if (st['marker-line-width'] !== undefined) {
ctx.globalAlpha = st['marker-line-opacity']; ctx.lineWidth = st['marker-line-width'];
} }
if (st['line-width']) { ctx.strokeStyle = st['marker-line-color'];
ctx.lineWidth = st['line-width'];
}
ctx.strokeStyle = st['line-color'];
// do not render for alpha = 0 // do not render for alpha = 0
if (ctx.globalAlpha > 0) { if (ctx.globalAlpha > 0) {
@ -53,14 +57,14 @@
// stroke // stroke
ctx.globalAlpha = 1.0; ctx.globalAlpha = 1.0;
if (st['line-color'] && st['line-width']) { if (st['marker-line-color'] && st['marker-line-width']) {
if (st['marker-line-opacity']) { if (st['marker-line-opacity']) {
ctx.globalAlpha = st['marker-line-opacity']; ctx.globalAlpha = st['marker-line-opacity'];
} }
if (st['line-width']) { if (st['marker-line-width']) {
ctx.lineWidth = st['line-width']; ctx.lineWidth = st['marker-line-width'];
} }
ctx.strokeStyle = st['line-color']; ctx.strokeStyle = st['marker-line-color'];
// do not render for alpha = 0 // do not render for alpha = 0
if (ctx.globalAlpha > 0) { if (ctx.globalAlpha > 0) {
@ -69,16 +73,19 @@
} }
} }
function renderSprite(ctx, st) { function renderSprite(ctx, img, st) {
var img = st['point-file'] || st['marker-file'];
var ratio = img.height/img.width; if(img.complete){
var w = st['marker-width'] || img.width; if (st['marker-fill-opacity'] !== undefined || st['marker-opacity'] !== undefined) {
var h = st['marker-width'] || st['marker-height'] || w*ratio; ctx.globalAlpha = st['marker-fill-opacity'] || st['marker-opacity'];
ctx.drawImage(img, 0, 0, w, h); }
ctx.drawImage(img, 0, 0, Math.min(img.width, MAX_SPRITE_RADIUS), Math.min(img.height, MAX_SPRITE_RADIUS));
}
} }
module.exports = { module.exports = {
renderPoint: renderPoint, renderPoint: renderPoint,
renderSprite: renderSprite, renderSprite: renderSprite,
renderRectangle: renderRectangle renderRectangle: renderRectangle,
MAX_SPRITE_RADIUS: MAX_SPRITE_RADIUS
}; };

View File

@ -0,0 +1,52 @@
var d3 = require('d3');
var jenks = require('turf-jenks');
function TorqueDataSource (tiles) {
this.tiles = tiles
}
module.exports = TorqueDataSource
TorqueDataSource.prototype.getName = function () {
return 'TorqueDataSource'
}
TorqueDataSource.prototype.getRamp = function (column, bins, method, callback) {
var ramp = []
var error = null
var values = Object.keys(this.tiles).map(function (t) {
return this.tiles[t].renderData;
}.bind(this)).reduce(function (p,c,i) {
for(var i = 0; i<c.length; i++) {
p.push(c[i]);
}
return p;
},[]);
var extent = d3.extent(values);
if (!method || method === 'equal' || method === 'jenks') {
var scale = d3.scale.linear().domain([0, bins]).range(extent)
ramp = d3.range(bins).map(scale)
} else if (method === 'quantiles') {
ramp = d3.scale.quantile().range(d3.range(bins)).domain(values).quantiles()
} else if (method === 'headstails') {
var sortedValues = values.sort(function(a, b) {
return a - b;
});
if (sortedValues.length < bins) {
error = 'Number of bins should be lower than total number of rows'
} else if (sortedValues.length === bins) {
ramp = sortedValues;
} else {
var mean = d3.mean(sortedValues);
ramp.push(mean);
for (var i = 1; i < bins; i++) {
ramp.push(d3.mean(sortedValues.filter(function (v) {
return v > ramp[length - 1];
})));
}
}
} else {
error = new Error('Quantification method ' + method + ' is not supported')
}
callback(error, ramp)
}

View File

@ -2,9 +2,12 @@ var torque = require('../');
var cartocss = require('./cartocss_render'); var cartocss = require('./cartocss_render');
var Profiler = require('../profiler'); var Profiler = require('../profiler');
var carto = global.carto || require('carto'); var carto = global.carto || require('carto');
var heat = require('./simpleheat'); var Filters = require('./torque_filters');
var turbocarto = require('turbo-carto');
var CartoDatasource = require('./datasource');
var ERROR_IMG_URL = 'http://s3.amazonaws.com/com.cartodb.assets.static/error.svg';
var TAU = Math.PI * 2;
var DEFAULT_CARTOCSS = [ var DEFAULT_CARTOCSS = [
'#layer {', '#layer {',
' marker-fill: #662506;', ' marker-fill: #662506;',
@ -20,24 +23,46 @@ var heat = require('./simpleheat');
].join('\n'); ].join('\n');
var COMP_OP_TO_CANVAS = { var COMP_OP_TO_CANVAS = {
"difference": "difference",
"src": 'source-over', "src": 'source-over',
"exclusion": "exclusion",
"dst": "destination-in",
"multiply": "multiply",
"contrast": "contrast",
"src-over": 'source-over', "src-over": 'source-over',
"screen": "screen",
"invert": "invert",
"dst-over": 'destination-over', "dst-over": 'destination-over',
"overlay": "overlay",
"invert-rgb": "invert",
"src-in": 'source-in', "src-in": 'source-in',
"dst-in": 'destination-in',
"src-out": 'source-out',
"dst-out": 'destination-out',
"src-atop": 'source-atop',
"dst-atop": 'destination-atop',
"xor": 'xor',
"darken": 'darken', "darken": 'darken',
"lighten": 'lighten' "dst-in": 'destination-in',
"lighten": 'lighten',
"src-out": 'source-out',
"color-dodge": "color-dodge",
"hue":"hue",
"dst-out": 'destination-out',
"color-burn":"color-burn",
"saturation":"saturation",
"src-atop": 'source-atop',
"hard-light":"hard-light",
"color":"color",
"dst-atop": 'destination-atop',
"soft-light":"soft-light",
"xor": 'xor'
} }
function compop2canvas(compop) { function compop2canvas(compop) {
return COMP_OP_TO_CANVAS[compop] || compop; return COMP_OP_TO_CANVAS[compop] || compop;
} }
// Take an input cartocss that may contain comments and remove them
var COMMENTS_RE = /\/\*.*?\*\/\n?/mg;
function stripComments(cartocss) {
return cartocss.replace(COMMENTS_RE, '');
}
// //
// this renderer just render points depending of the value // this renderer just render points depending of the value
// //
@ -46,31 +71,42 @@ var heat = require('./simpleheat');
throw new Error("canvas can't be undefined"); throw new Error("canvas can't be undefined");
} }
this.options = options; this.options = options;
this.layer = options.layer;
this._canvas = canvas; this._canvas = canvas;
this._ctx = canvas.getContext('2d'); this._ctx = canvas.getContext('2d');
this._heat = heat(this._canvas);
this._heat.max(255);
this._sprites = []; // sprites per layer this._sprites = []; // sprites per layer
this._shader = null; this._shader = null;
this._icons = {};
this._iconsToLoad = 0;
this._filters = new Filters(this._canvas, {canvasClass: options.canvasClass});
this.setCartoCSS(this.options.cartocss || DEFAULT_CARTOCSS); this.setCartoCSS(this.options.cartocss || DEFAULT_CARTOCSS);
this.TILE_SIZE = 256; this.TILE_SIZE = 256;
this._style = null;
this._gradients = {};
this._forcePoints = false;
} }
PointRenderer.prototype = { torque.extend(PointRenderer.prototype, torque.Event, {
clearCanvas: function() { clearCanvas: function() {
var canvas = this._canvas; if (this._Map) {
var color = this._Map['-torque-clear-color'] var canvas = this._canvas;
// shortcut for the default value var color = this._Map['-torque-clear-color']
if (color === "rgba(255, 255, 255, 0)" || !color) { // shortcut for the default value
this._canvas.width = this._canvas.width;
} else {
var ctx = this._ctx; var ctx = this._ctx;
ctx.setTransform(1, 0, 0, 1, 0, 0); if (color === "rgba(255, 255, 255, 0)" || !color) {
var compop = this._Map['comp-op'] ctx.save();
ctx.globalCompositeOperation = compop2canvas(compop); ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.fillStyle = color; ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.restore();
} else {
ctx.setTransform(1, 0, 0, 1, 0, 0);
var compop = this._Map['comp-op']
ctx.globalCompositeOperation = compop2canvas(compop) || compop;
ctx.fillStyle = color;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
} }
}, },
@ -82,9 +118,27 @@ var heat = require('./simpleheat');
// //
// sets the cartocss style to render stuff // sets the cartocss style to render stuff
// //
setCartoCSS: function(cartocss) { setCartoCSS: function(cartocss, callback) {
// clean sprites var self = this;
this.setShader(new carto.RendererJS().render(cartocss));
this.style = stripComments(cartocss);
if (PointRenderer.isTurboCarto(this.style) && self.layer) {
var datasource = new CartoDatasource(self.layer._tiles);
turbocarto(this.style, datasource, function (err, parsedCartoCSS) {
if (err) {
return callback(err, null);
}
self.setShader(new carto.RendererJS().render(parsedCartoCSS));
self.layer.redraw();
self.layer.animator.start();
callback && callback();
});
} else {
self.setShader(new carto.RendererJS().render(this.style));
callback && callback();
}
}, },
setShader: function(shader) { setShader: function(shader) {
@ -92,6 +146,12 @@ var heat = require('./simpleheat');
this._sprites = []; this._sprites = [];
this._shader = shader; this._shader = shader;
this._Map = this._shader.getDefault().getStyle({}, { zoom: 0 }); this._Map = this._shader.getDefault().getStyle({}, { zoom: 0 });
var img_names = this._shader.getImageURLs();
if (this.layer && this.layer.showLimitErrors) {
img_names.push(ERROR_IMG_URL);
}
this._preloadIcons(img_names);
}, },
clearSpriteCache: function() { clearSpriteCache: function() {
@ -103,30 +163,48 @@ var heat = require('./simpleheat');
// generate sprite based on cartocss style // generate sprite based on cartocss style
// //
generateSprite: function(shader, value, shaderVars) { generateSprite: function(shader, value, shaderVars) {
var self = this;
var prof = Profiler.metric('torque.renderer.point.generateSprite').start(); var prof = Profiler.metric('torque.renderer.point.generateSprite').start();
var st = shader.getStyle({ var st = shader.getStyle({
value: value value: value
}, shaderVars); }, shaderVars);
if(this._style === null || this._style !== st){
this._style = st;
}
var pointSize = st['marker-width']; var pointSize = st['marker-width'];
if (!pointSize) { if (!pointSize) {
return null; return null;
} }
if (st['marker-opacity'] === 0 && !st['line-opacity']) { if (st['marker-opacity'] === 0 && !st['marker-line-opacity']) {
return null; return null;
} }
var canvas = this._createCanvas(); var canvas = this._createCanvas();
// take into account the exterior ring to calculate the size
var canvasSize = (st['line-width'] || 0) + pointSize*2;
var ctx = canvas.getContext('2d'); var ctx = canvas.getContext('2d');
var w = ctx.width = canvas.width = ctx.height = canvas.height = Math.ceil(canvasSize);
ctx.translate(w/2, w/2);
if(st['point-file'] || st['marker-file']) { var markerFile = st["marker-file"] || st["point-file"];
cartocss.renderSprite(ctx, st); var qualifiedUrl = markerFile && this._qualifyURL(markerFile);
if (qualifiedUrl && this._iconsToLoad <= 0 && this._icons[qualifiedUrl]) {
var img = this._icons[qualifiedUrl];
var dWidth = Math.min(st['marker-width'] * 2 || img.width, cartocss.MAX_SPRITE_RADIUS * 2);
var dHeight = Math.min((st['marker-height'] || dWidth) * (img.width / img.height), cartocss.MAX_SPRITE_RADIUS * 2);
canvas.width = ctx.width = dWidth;
canvas.height = ctx.height = dHeight;
ctx.scale(dWidth/img.width, dHeight/img.height);
cartocss.renderSprite(ctx, img, st);
} else { } else {
// take into account the exterior ring to calculate the size
var canvasSize = (st['marker-line-width'] || 0) + pointSize*2;
var w = ctx.width = canvas.width = ctx.height = canvas.height = Math.ceil(canvasSize);
ctx.translate(w/2, w/2);
var mt = st['marker-type']; var mt = st['marker-type'];
if (mt && mt === 'rectangle') { if (mt && mt === 'rectangle') {
cartocss.renderRectangle(ctx, st); cartocss.renderRectangle(ctx, st);
@ -140,15 +218,33 @@ var heat = require('./simpleheat');
i.src = canvas.toDataURL(); i.src = canvas.toDataURL();
return i; return i;
} }
return canvas; return canvas;
}, },
// //
// renders all the layers (and frames for each layer) from cartocss // renders all the layers (and frames for each layer) from cartocss
// //
renderTile: function(tile, key, pos) { renderTile: function(tile, keys, callback) {
this._renderTile(tile, key, 0, null, null, null, pos); if (tile && tile.error) {
/*var prof = Profiler.metric('torque.renderer.point.renderLayers').start(); this._renderErrorTile(tile);
return false;
}
if (this._iconsToLoad > 0) {
this.on('allIconsLoaded', function() {
this.renderTile.apply(this, [tile, keys, callback]);
});
return false;
}
// convert scalar key to keys array
if (typeof keys.length === 'undefined') {
keys = [keys];
}
var prof = Profiler.metric('torque.renderer.point.renderLayers').start();
var layers = this._shader.getLayers(); var layers = this._shader.getLayers();
for(var i = 0, n = layers.length; i < n; ++i ) { for(var i = 0, n = layers.length; i < n; ++i ) {
var layer = layers[i]; var layer = layers[i];
@ -158,12 +254,24 @@ var heat = require('./simpleheat');
for(var fr = 0; fr < layer.frames().length; ++fr) { for(var fr = 0; fr < layer.frames().length; ++fr) {
var frame = layer.frames()[fr]; var frame = layer.frames()[fr];
var fr_sprites = sprites[frame] || (sprites[frame] = []); var fr_sprites = sprites[frame] || (sprites[frame] = []);
this._renderTile(tile, key - frame, frame, fr_sprites, layer); for (var k = 0, len = keys.length; k < len; k++) {
try {
this._renderTile(tile, keys[k] - frame, frame, fr_sprites, layer);
} catch (error) {
if (callback) {
return callback(error);
}
throw new Error(error);
}
}
} }
} }
} }
prof.end(true); prof.end(true);
*/
return callback && callback(null);
}, },
_createCanvas: function() { _createCanvas: function() {
@ -178,38 +286,79 @@ var heat = require('./simpleheat');
: new Image(); : new Image();
}, },
_setImageSrc: function(img, url, callback) {
if (this.options.setImageSrc) {
this.options.setImageSrc(img, url, callback);
} else {
img.onload = function(){
callback(null);
};
img.onerror = function(){
callback(new Error('Could not load image'));
};
img.src = url;
}
},
_qualifyURL: function(url) {
if (typeof this.options.qualifyURL !== "undefined"){
return this.options.qualifyURL(url);
}
else{
var a = document.createElement('a');
a.href = url;
return a.href;
}
},
_renderErrorTile: function(tile) {
if(this.layer.showLimitErrors) {
var img = this._icons[ERROR_IMG_URL];
img && this._ctx.drawImage(img, 0, 0, this.TILE_SIZE, this.TILE_SIZE);
}
},
// //
// renders a tile in the canvas for key defined in // renders a tile in the canvas for key defined in
// the torque tile // the torque tile
// //
_renderTile: function(tile, key, frame_offset, sprites, shader, shaderVars, pos) { _renderTile: function(tile, key, frame_offset, sprites, shader, shaderVars) {
if(!this._canvas || !this._heat) return; if (!this._canvas) return;
var prof = Profiler.metric('torque.renderer.point.renderTile').start(); var prof = Profiler.metric('torque.renderer.point.renderTile').start();
var ctx = this._ctx; var ctx = this._ctx;
var blendMode = compop2canvas(shader.eval('comp-op')) || this.options.blendmode;
if (blendMode) {
ctx.globalCompositeOperation = blendMode;
}
if (this.options.cumulative && key > tile.maxDate) {
//TODO: precache because this tile is not going to change
key = tile.maxDate;
}
var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1) var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1)
var activePixels = tile.timeCount[key]; var activePixels = tile.timeCount[key];
var anchor = this.options.resolution/2;
if (activePixels) { if (activePixels) {
var pixelIndex = tile.timeIndex[key]; var pixelIndex = tile.timeIndex[key];
for(var p = 0; p < activePixels; ++p) { for(var p = 0; p < activePixels; ++p) {
var posIdx = tile.renderDataPos[pixelIndex + p]; var posIdx = tile.renderDataPos[pixelIndex + p];
var c = tile.renderData[pixelIndex + p]; var c = tile.renderData[pixelIndex + p];
if(c) { if (c) {
var x = tile.x[posIdx]; var sp = sprites[c];
var y = tileMax - tile.y[posIdx]; // flip mercator if (sp === undefined) {
this._heat.add([pos.x + x, pos.y + y, c]); sp = sprites[c] = this.generateSprite(shader, c, torque.extend({ zoom: tile.z, 'frame-offset': frame_offset }, shaderVars));
}
if (sp) {
var x = tile.x[posIdx]- (sp.width >> 1) + anchor;
var y = tileMax - tile.y[posIdx] + anchor; // flip mercator
ctx.drawImage(sp, x, y - (sp.height >> 1));
}
} }
} }
} }
prof.end(true);
},
flush: function() {
this._ctx.setTransform(1, 0, 0, 1, 0, 0); prof.end(true);
if(!this._heat) return;
this._heat.draw();
this._heat.clear();
}, },
setBlendMode: function(b) { setBlendMode: function(b) {
@ -246,6 +395,23 @@ var heat = require('./simpleheat');
return positions; return positions;
}, },
/**
* returns an array with all the values for the active pixels
* @tile tile object
* @step integer with the step
* @values (optional) an array where the values will be placed
*/
getValues: function(tile, step, values) {
values = values || [];
var activePixels = tile.timeCount[step];
var pixelIndex = tile.timeIndex[step];
for(var p = 0; p < activePixels; ++p) {
var posIdx = tile.renderDataPos[pixelIndex + p];
values.push(tile.renderData[pixelIndex + p]);
}
return values;
},
// return the value for x, y (tile coordinates) // return the value for x, y (tile coordinates)
// null for no value // null for no value
getValueFor: function(tile, step, px, py) { getValueFor: function(tile, step, px, py) {
@ -279,9 +445,112 @@ var heat = require('./simpleheat');
} }
} }
return null; return null;
} },
}; _preloadIcons: function(img_names) {
var self = this;
if (img_names.length > 0 && !this._forcePoints) {
var qualifiedImageUrlSet = Object.keys(img_names.reduce(function(imgNamesMap, imgName) {
var qualifiedUrl = self._qualifyURL(imgName);
if (!self._icons[qualifiedUrl]) {
imgNamesMap[qualifiedUrl] = true;
}
return imgNamesMap;
}, {}));
var filtered = self._shader.getLayers().some(function(layer) {
return typeof layer.shader["image-filters"] !== "undefined";
});
this._iconsToLoad += qualifiedImageUrlSet.length;
qualifiedImageUrlSet.forEach(function(qualifiedImageUrl) {
self._icons[qualifiedImageUrl] = null;
var img = self._createImage();
if (filtered) {
img.crossOrigin = 'Anonymous';
}
self._setImageSrc(img, qualifiedImageUrl, function(err) {
if (err) {
self._forcePoints = true;
self.clearSpriteCache();
self._iconsToLoad = 0;
self.fire("allIconsLoaded");
if(filtered) {
console.info("Only CORS-enabled, or same domain image-files can be used in combination with image-filters");
}
console.error("Couldn't get marker-file " + qualifiedImageUrl);
} else {
self._icons[qualifiedImageUrl] = img;
self._iconsToLoad--;
if (self._iconsToLoad <= 0){
self.clearSpriteCache();
self.fire("allIconsLoaded");
}
}
});
});
} else {
this.fire("allIconsLoaded");
}
},
applyFilters: function(){
if(this._style){
if(this._style['image-filters']){
function gradientKey(imf){
var hash = ""
for(var i = 0; i < imf.args.length; i++){
var rgb = imf.args[i].rgb;
hash += rgb[0] + ":" + rgb[1] + ":" + rgb[2];
}
return hash;
}
var gradient = this._gradients[gradientKey(this._style['image-filters'])];
if(!gradient){
function componentToHex(c) {
var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
function rgbToHex(r, g, b) {
return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}
gradient = {};
var colorize = this._style['image-filters'].args;
var increment = 1/colorize.length;
for (var i = 0; i < colorize.length; i++){
var key = increment * i + increment;
var rgb = colorize[i].rgb;
var formattedColor = rgbToHex(rgb[0], rgb[1], rgb[2]);
gradient[key] = formattedColor;
}
this._gradients[gradientKey(this._style['image-filters'])] = gradient;
}
this._filters.gradient(gradient);
this._filters.draw();
}
}
}
});
PointRenderer.isTurboCarto = function (cartocss) {
var reservedWords = ['ramp', 'colorbrewer', 'buckets']
var isTurbo = reservedWords
.map(function (w) {
return w + '('
})
.map(String.prototype.indexOf.bind(cartocss))
.every(function (f) { return f === -1 })
return !isTurbo
}
// exports public api // exports public api

Some files were not shown because too many files have changed in this diff Show More