Compare commits
806 Commits
privacy-ma
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
11b73bbc9a | ||
|
f6217eaed0 | ||
|
63e70d1446 | ||
|
62bc50b129 | ||
|
c62c4f548e | ||
|
3a782117f5 | ||
|
58664a2f47 | ||
|
4d2540ef98 | ||
|
eb06dd1e63 | ||
|
a44bf1866c | ||
|
adbeb066cc | ||
|
8da4889d17 | ||
|
dae2531d5c | ||
|
c2346d5979 | ||
|
db9290d990 | ||
|
5529351215 | ||
|
878d5c418b | ||
|
3f3bd97dd6 | ||
|
47a2c4fda8 | ||
|
0edffef74b | ||
|
2f97d7fda0 | ||
|
9f66475278 | ||
|
9b680db46c | ||
|
890f4a5da1 | ||
|
71b5c07420 | ||
|
05fb3cfc18 | ||
|
23101417f2 | ||
|
ef9de16c2d | ||
|
bb0f5118ed | ||
|
be0d9d5063 | ||
|
26252f3841 | ||
|
ca8634530e | ||
|
a06871eb42 | ||
|
ebd978fe7d | ||
|
7200f9b7fe | ||
|
69857f7335 | ||
|
6489c8a743 | ||
|
96fa54bb98 | ||
|
80a7757fdf | ||
|
8664c32b74 | ||
|
54f5389805 | ||
|
8142d2622e | ||
|
6a60af93b7 | ||
|
286473fadb | ||
|
69ad01bf9e | ||
|
7cf5d6a590 | ||
|
3f71d1e40c | ||
|
397dec86b1 | ||
|
40142ca244 | ||
|
ce414701ab | ||
|
a0e108ac23 | ||
|
4cfeff4054 | ||
|
03b0f4059a | ||
|
f4720e0736 | ||
|
e784dcb048 | ||
|
783303bc31 | ||
|
7dc5703cf4 | ||
|
efca29f374 | ||
|
8a3bccd0c9 | ||
|
a8da0581d1 | ||
|
be43a32eeb | ||
|
7cbe86259e | ||
|
02575e0991 | ||
|
7178906519 | ||
|
5bf0330d0e | ||
|
5a507f2723 | ||
|
35fa94ba7b | ||
|
3e293ba982 | ||
|
ea3a49586c | ||
|
7a64469f57 | ||
|
7b8fd95f69 | ||
|
e9e30b7541 | ||
|
9012fd7d68 | ||
|
a01dd84505 | ||
|
eb09121165 | ||
|
a0e02c1c03 | ||
|
fa25acf13e | ||
|
ebadade6c1 | ||
|
8573862459 | ||
|
caee1c28c1 | ||
|
64fdddd1a5 | ||
|
9d76b2d4fd | ||
|
72faba5cb7 | ||
|
d1922506ac | ||
|
6d8f6c746a | ||
|
d70af4d2e4 | ||
|
d137c14372 | ||
|
b631de3c7d | ||
|
bffc34f87a | ||
|
fb5f13ef2f | ||
|
965cbffb70 | ||
|
ed22c66062 | ||
|
208c1de62c | ||
|
60b8a065a9 | ||
|
f007de5883 | ||
|
b2c92475c4 | ||
|
fd0ed66c9f | ||
|
54b84f0312 | ||
|
61c508fd7b | ||
|
a1b6483d64 | ||
|
6cb9051480 | ||
|
cde81fc1e7 | ||
|
5e83f5bd8b | ||
|
0f4f8a5319 | ||
|
e6aaa10f67 | ||
|
03248457e1 | ||
|
3fa971d044 | ||
|
197c3d7824 | ||
|
5666fbc187 | ||
|
07e9ee6d21 | ||
|
bdab824733 | ||
|
c2512a9b1e | ||
|
2f210b8783 | ||
|
6314352a19 | ||
|
95c7ba2a7e | ||
|
6aa54bfb0c | ||
|
b9765821be | ||
|
7f0a61a8c4 | ||
|
2dee3662ae | ||
|
bb6a4cbc06 | ||
|
14dbf9b7ec | ||
|
29bf52a70b | ||
|
00a12cf968 | ||
|
3c43265dcc | ||
|
9fa066c3bc | ||
|
6f56aa05ad | ||
|
6f2b3b9cc2 | ||
|
f7efb15a8f | ||
|
9b67ec1279 | ||
|
d80249f83d | ||
|
4a049eedce | ||
|
742c2d9808 | ||
|
a8385cff5c | ||
|
e6451e0e7b | ||
|
792a66ccf9 | ||
|
5d9b02a6da | ||
|
feb9fa3e01 | ||
|
cf5a29c3a7 | ||
|
27306dd917 | ||
|
5382d62141 | ||
|
a67ad45b9c | ||
|
664ab3f28b | ||
|
23d2d2a60e | ||
|
b597fba4ae | ||
|
73d1b1a9b5 | ||
|
4c28eb7bdd | ||
|
c3f25b08de | ||
|
9c9c7253ba | ||
|
69cdd20c36 | ||
|
e0ddf8c9d1 | ||
|
ffa1435d20 | ||
|
34fee901ca | ||
|
6311531550 | ||
|
27a752f49c | ||
|
b7e00af3f7 | ||
|
e745fac67b | ||
|
f5bfaf7585 | ||
|
ea6fc57384 | ||
|
b75688dcd9 | ||
|
8d39f09a68 | ||
|
f669429861 | ||
|
1aacc38d49 | ||
|
daa9dd42b3 | ||
|
8e714b6a1a | ||
|
5d89990119 | ||
|
e83bcaee6d | ||
|
c998860ad3 | ||
|
ae5afddba7 | ||
|
44c8e77213 | ||
|
03bc7695a3 | ||
|
4cfbe82ae1 | ||
|
813b3b60dc | ||
|
deced717fd | ||
|
4e91bd5856 | ||
|
80172ac547 | ||
|
d50d74571b | ||
|
88b2be378d | ||
|
f9e6b4f2f9 | ||
|
b94b4812c7 | ||
|
490d91fe15 | ||
|
8b860d4205 | ||
|
a82dbfb850 | ||
|
3752aacf33 | ||
|
771c92fb2f | ||
|
2f6306dae3 | ||
|
aac5d4a48b | ||
|
b1fb8856da | ||
|
a87657d5d1 | ||
|
e20286ed84 | ||
|
ee95c112f9 | ||
|
c847784a8f | ||
|
79c48b5521 | ||
|
db8ad92e33 | ||
|
7a33d8a1de | ||
|
d218c2da24 | ||
|
cee1c7b16b | ||
|
b9531f95ce | ||
|
16bac52b91 | ||
|
85d377e6b0 | ||
|
ba156219fd | ||
|
2e1a020c3c | ||
|
16564df47e | ||
|
62fc84b9be | ||
|
65a115e9b1 | ||
|
94496795ee | ||
|
47f02ce23d | ||
|
56b7267ec5 | ||
|
fca222a05b | ||
|
01ffec1a34 | ||
|
35251805bf | ||
|
ddf487f56d | ||
|
b614e25855 | ||
|
dbc5309ae0 | ||
|
c2d10feec9 | ||
|
dfed86e7d5 | ||
|
0bfe358e39 | ||
|
6be4d857e5 | ||
|
086da527bd | ||
|
8fe4c8f610 | ||
|
8a14fe546a | ||
|
2bcb7d8036 | ||
|
46e9839da1 | ||
|
4b6c70d462 | ||
|
b5a2e88f1c | ||
|
f52a47a04e | ||
|
d1ab5620c6 | ||
|
bfc2489b5c | ||
|
4cd282a6d4 | ||
|
3f4279a355 | ||
|
d12d30cf82 | ||
|
933c95be9c | ||
|
5f92bdc9da | ||
|
2377029350 | ||
|
0e9184e026 | ||
|
1ff54b9018 | ||
|
7f75022168 | ||
|
31af420c6d | ||
|
8184175642 | ||
|
80293501e5 | ||
|
2628bcb9ff | ||
|
d196b617b8 | ||
|
959e8c48dc | ||
|
31a81e760b | ||
|
74a536da26 | ||
|
178eb5700f | ||
|
b15585128f | ||
|
52cc4c663c | ||
|
30bd226d71 | ||
|
9f759caaed | ||
|
2fe9c737cd | ||
|
4cb2946486 | ||
|
4d69594f2a | ||
|
96adfc2836 | ||
|
99e8a242e4 | ||
|
50789565c4 | ||
|
12816745b5 | ||
|
1defdcba34 | ||
|
3e93e8f753 | ||
|
09ff7e273d | ||
|
3d290e259b | ||
|
2677f80814 | ||
|
eb2e2c7b25 | ||
|
33396b4871 | ||
|
4f2bc0b99a | ||
|
d9ae9b6ba5 | ||
|
27e3480130 | ||
|
6638a13e14 | ||
|
abe1dd4570 | ||
|
40044e5448 | ||
|
01b30d18ca | ||
|
3515046614 | ||
|
b2b10868b0 | ||
|
fd828bb6b3 | ||
|
4eb4bdbdc1 | ||
|
3a0220194b | ||
|
a04f1a7d5b | ||
|
786af47be4 | ||
|
b0e04b7611 | ||
|
cd9e1a3457 | ||
|
990c52999a | ||
|
2675df3526 | ||
|
093fc94076 | ||
|
0749bdd0e1 | ||
|
5c0232fa5f | ||
|
2ced306f23 | ||
|
56cfe309bd | ||
|
4fe5cd2150 | ||
|
7441a95b1a | ||
|
a3b07fc649 | ||
|
83cdcd11eb | ||
|
6172d9dd10 | ||
|
db961cf4b2 | ||
|
d478fdc1b0 | ||
|
77d9ac810c | ||
|
985c0b0eb5 | ||
|
31920d0d73 | ||
|
2d5542a28c | ||
|
5413f4cb82 | ||
|
10d65267e6 | ||
|
08e59543dd | ||
|
29a05da8b8 | ||
|
b4ca93271b | ||
|
fd5c3aeec1 | ||
|
2bbf0576eb | ||
|
b6169fb31a | ||
|
6f35d6399a | ||
|
8f1bcde31f | ||
|
9d6a762f12 | ||
|
d6b15282b7 | ||
|
1f88da6439 | ||
|
1bdaed7bcb | ||
|
5767ed7f35 | ||
|
9fe8d9b7f3 | ||
|
dffb469c5c | ||
|
9f25dea8a6 | ||
|
cf683238eb | ||
|
d4bbfb7431 | ||
|
ff269a5ecf | ||
|
d7a0fa8ed1 | ||
|
aa8c61b442 | ||
|
9cc7779858 | ||
|
3099b7b881 | ||
|
3eb011360b | ||
|
b212913530 | ||
|
e4aa398f6e | ||
|
e2461d6997 | ||
|
191e762d35 | ||
|
00e3ddfe99 | ||
|
ef03cbe98c | ||
|
e4c61127e1 | ||
|
a49bf13a9d | ||
|
efa11680c4 | ||
|
a88a0474d3 | ||
|
13affc5716 | ||
|
008c598e1c | ||
|
4527d4a300 | ||
|
334e2593d5 | ||
|
ff99d21c71 | ||
|
57c6afb266 | ||
|
a69527b637 | ||
|
cd66a811d8 | ||
|
1ec0dc6585 | ||
|
f02dd5a710 | ||
|
07d03735a7 | ||
|
87df24e914 | ||
|
e68e7d3d37 | ||
|
95453ab4b3 | ||
|
84f7537969 | ||
|
10589b2d28 | ||
|
d4c994b6d2 | ||
|
e4a913cbad | ||
|
d5948c8009 | ||
|
4385c6ad9a | ||
|
39773b3151 | ||
|
3a10865f09 | ||
|
e46de301f5 | ||
|
b3c8cd76c6 | ||
|
5be36ca15a | ||
|
288321b383 | ||
|
429e2d5852 | ||
|
ea1d7dc48a | ||
|
2e03c784ae | ||
|
f9bf4264b3 | ||
|
388ef63f4d | ||
|
66de9f9c49 | ||
|
d5c3b0b5b4 | ||
|
6f0ea37dbe | ||
|
8d1d55b7d1 | ||
|
ffdc70a60d | ||
|
83a622a3f0 | ||
|
efcfc13546 | ||
|
3a06914cc2 | ||
|
88fe98447c | ||
|
f71c0c8473 | ||
|
5017213a3b | ||
|
ee43ef5fa1 | ||
|
64e12f4ea8 | ||
|
b419cb555f | ||
|
579326954b | ||
|
d41e42f838 | ||
|
b2a1d6a0fa | ||
|
5c2fc2a9a8 | ||
|
a2067687f9 | ||
|
2925f09df2 | ||
|
973aa487dc | ||
|
28a11c99b7 | ||
|
e015282f9c | ||
|
786d6c1edc | ||
|
df99c918d1 | ||
|
4744ccd661 | ||
|
9dcaf60d83 | ||
|
ddc9c2768f | ||
|
538f3e3912 | ||
|
be7046e5a0 | ||
|
4ed644feaa | ||
|
ebc1446063 | ||
|
9cf50b9864 | ||
|
ed370dce54 | ||
|
f621ae268b | ||
|
9ca31c2963 | ||
|
cef13cbf37 | ||
|
2b12623b05 | ||
|
c0b72b470c | ||
|
f63600ee28 | ||
|
f883575d10 | ||
|
bf8cdf6e59 | ||
|
999b4d49f4 | ||
|
321258a891 | ||
|
621fe55ea9 | ||
|
bc953b1185 | ||
|
00a93d8c48 | ||
|
feccf2809b | ||
|
465c47e40d | ||
|
147cdbf1b4 | ||
|
9ca2d5e774 | ||
|
3eef183945 | ||
|
52b3521557 | ||
|
3476c74f1c | ||
|
ad9f7c40b1 | ||
|
9c17d7a1bc | ||
|
9486bd9667 | ||
|
fa5791483e | ||
|
645da00ce1 | ||
|
4b10cc37d0 | ||
|
89b6819e53 | ||
|
adbeebb1c1 | ||
|
aabf0f234c | ||
|
c14eed8756 | ||
|
581d7a337d | ||
|
cdf3708a3c | ||
|
b8d8892951 | ||
|
b3c2af660c | ||
|
70800798da | ||
|
a27960fbe7 | ||
|
3309b2cfad | ||
|
c3b22324f1 | ||
|
58345d248e | ||
|
e98c518d09 | ||
|
5c8b3c0908 | ||
|
d7a284082a | ||
|
aaa8b819ed | ||
|
36b4fa9c0c | ||
|
25e61e064f | ||
|
caf21dce1f | ||
|
c50b60db9c | ||
|
e0c68c17e5 | ||
|
db914f65cf | ||
|
6e73f8acea | ||
|
ee6b3e4c7f | ||
|
995c209958 | ||
|
f775df9e9c | ||
|
27d983d646 | ||
|
ee07260d7b | ||
|
64d05276ae | ||
|
d95399502c | ||
|
2ae4b71df6 | ||
|
2652f6c6d8 | ||
|
8d8d65050d | ||
|
7626ebe3b6 | ||
|
3134aa828c | ||
|
c04ab74a97 | ||
|
e96a1c7118 | ||
|
8adc55fdd4 | ||
|
e0e502a083 | ||
|
9e7de2bcbd | ||
|
c3988b14a6 | ||
|
a0417d8bc3 | ||
|
a434bd8640 | ||
|
8938c25280 | ||
|
d5be1f115f | ||
|
c058a55c58 | ||
|
e6c9f03e3d | ||
|
a935bfc93e | ||
|
c3dd3af184 | ||
|
ce6351a2c4 | ||
|
219a3f5888 | ||
|
a244fa183c | ||
|
131f116487 | ||
|
f63b037d0e | ||
|
35e28b22c7 | ||
|
73f8212c2f | ||
|
302ebf97cb | ||
|
a2696195f4 | ||
|
e657f349df | ||
|
567511f694 | ||
|
4fea2e32c1 | ||
|
3ead777645 | ||
|
6232e16002 | ||
|
086c77c379 | ||
|
309bcb09f3 | ||
|
f04b149b23 | ||
|
8af1b8288b | ||
|
d04eb9576c | ||
|
d360dffe28 | ||
|
80ef7bf727 | ||
|
2af620ee74 | ||
|
c855c1c212 | ||
|
2c7f317af7 | ||
|
0a8708d044 | ||
|
734e6e119a | ||
|
3476c44efa | ||
|
fae792067e | ||
|
204ed0903c | ||
|
a67d9df45a | ||
|
7359471605 | ||
|
a7ff63edfc | ||
|
7958c81c24 | ||
|
916871365f | ||
|
ddffe412c6 | ||
|
ef2c90d28c | ||
|
81892a3231 | ||
|
2464e5cdf5 | ||
|
0305d15106 | ||
|
149c741a03 | ||
|
49b093d3de | ||
|
286b23ebaf | ||
|
cfc702f98d | ||
|
142ae1f528 | ||
|
1c25e13cec | ||
|
ac3df42b15 | ||
|
c0131cdebf | ||
|
656d082568 | ||
|
2ceeba0d82 | ||
|
f2a4c22dc7 | ||
|
8bc49bcb3e | ||
|
043e7b0090 | ||
|
6c094e3ba9 | ||
|
cfe01c5dbe | ||
|
7e43d0ecee | ||
|
6ba2e42625 | ||
|
ef42324b29 | ||
|
d744c9a497 | ||
|
fa8a9bbc2b | ||
|
b605bd56ce | ||
|
9a1571d79e | ||
|
dbc3c1c8f3 | ||
|
5006d6495d | ||
|
d81bb5855c | ||
|
d5e8007dce | ||
|
767fae6272 | ||
|
5a27243f07 | ||
|
ece11bb3f3 | ||
|
fbac1510dc | ||
|
da7cf9d244 | ||
|
db41e24b42 | ||
|
847f3fc2f4 | ||
|
dfc8c982d9 | ||
|
2c04ed0a40 | ||
|
1d3e01a655 | ||
|
4ab654ac89 | ||
|
dca842a08c | ||
|
8dffb1a8d2 | ||
|
ecb72d9e8a | ||
|
da7144a7fd | ||
|
81054b657a | ||
|
5ec6054487 | ||
|
54f3fd2294 | ||
|
959f216e82 | ||
|
d27f9b0919 | ||
|
c82c55affd | ||
|
b4f5ae1667 | ||
|
038777c8cc | ||
|
45a3b57946 | ||
|
830fc86eba | ||
|
f0b7f09140 | ||
|
7d679cde70 | ||
|
117f13c5e9 | ||
|
a1d59585fb | ||
|
395edc39e0 | ||
|
9b421d7d7f | ||
|
3f33dc3428 | ||
|
cd75867254 | ||
|
7cb1d7b33b | ||
|
a56d4fe627 | ||
|
d7ebab04d5 | ||
|
94b58126df | ||
|
f65fae5639 | ||
|
9fcddf9ec3 | ||
|
dc81b7a335 | ||
|
aca16f2549 | ||
|
42ef4bcd48 | ||
|
1696005d77 | ||
|
446bd632c8 | ||
|
4e5b1929c7 | ||
|
47a14ed7d3 | ||
|
135400043e | ||
|
4bf358f59e | ||
|
b73d687141 | ||
|
cd7146f6e0 | ||
|
ea79f007a2 | ||
|
fdc63548d4 | ||
|
b2c37b1310 | ||
|
d85189b7f4 | ||
|
0ea62d36e7 | ||
|
24413a706f | ||
|
38f0e3d814 | ||
|
fe09fe9e0c | ||
|
8ee054fa89 | ||
|
9c5859be41 | ||
|
3b50c7cf5d | ||
|
30c2bf6a47 | ||
|
4bc2a8492a | ||
|
019ac452f0 | ||
|
26f185aa09 | ||
|
508b75e4da | ||
|
70a55ebfba | ||
|
bf25f76761 | ||
|
1449a9df85 | ||
|
7826a914d9 | ||
|
e649d785f3 | ||
|
cadbb8fd72 | ||
|
b5acfb30a7 | ||
|
cb7c7da7c5 | ||
|
93e0b8129b | ||
|
9a0151d717 | ||
|
dac3246fcd | ||
|
8d8dbb29b4 | ||
|
1e106b23b9 | ||
|
bfcd6ca06f | ||
|
1c0057b0ed | ||
|
1a2c6f2ab0 | ||
|
fbeddab4a3 | ||
|
17840c4403 | ||
|
224c14783f | ||
|
b95ab3bac5 | ||
|
45e577c872 | ||
|
434684df09 | ||
|
4d596066df | ||
|
368f5b1526 | ||
|
b295bdbd5f | ||
|
d1c224ff13 | ||
|
8241bd6c8c | ||
|
91b056329b | ||
|
37c35732d7 | ||
|
1113a100d1 | ||
|
06ed46f6b8 | ||
|
d98402d9cd | ||
|
5dc39a5e32 | ||
|
3c41470d7a | ||
|
c21c715bf4 | ||
|
e9cece69bd | ||
|
a30d5fc269 | ||
|
fc3584b01f | ||
|
2f8443fe6e | ||
|
ead86bad00 | ||
|
3cdd89ab24 | ||
|
731206090a | ||
|
2074a720a1 | ||
|
1d5414a31d | ||
|
994aeedf95 | ||
|
05e1137fe9 | ||
|
b4330f68a6 | ||
|
728136d964 | ||
|
9c5c290c4e | ||
|
20b88a72ff | ||
|
50605303f1 | ||
|
2e79d7ee90 | ||
|
27bba39f07 | ||
|
c3b159b64d | ||
|
e9f738914c | ||
|
d25011681a | ||
|
90de3db461 | ||
|
68c68f3a02 | ||
|
495082c29e | ||
|
b1f6a46e8e | ||
|
08b66b3119 | ||
|
d82fe9d057 | ||
|
8a8455922d | ||
|
f002f3d9d4 | ||
|
43a3c64d21 | ||
|
88ea3bee66 | ||
|
ba1ae9856c | ||
|
a3916038e1 | ||
|
dd7544e4b4 | ||
|
df5acbb96c | ||
|
34c5fba9d9 | ||
|
502b200234 | ||
|
2aa4fc20ef | ||
|
a8d9311f88 | ||
|
e86fd7fb44 | ||
|
b98efc112e | ||
|
d2dd3353d3 | ||
|
f7d81998fc | ||
|
9f35092943 | ||
|
6c45a805d2 | ||
|
40f6a4913f | ||
|
e8fee1659b | ||
|
1e83584d12 | ||
|
d44b2db551 | ||
|
e1e928733f | ||
|
29bdbd29c6 | ||
|
410037d4a2 | ||
|
6ecf054ac0 | ||
|
4f251cd8cc | ||
|
5efdf16c61 | ||
|
7499e8cf6a | ||
|
3471a2ac6d | ||
|
a44b93e251 | ||
|
2e8813c9ff | ||
|
7463b461e6 | ||
|
7d3d325d7a | ||
|
d6a1d5d808 | ||
|
022d46b56b | ||
|
ee4f600da5 | ||
|
02da984769 | ||
|
41e9db8235 | ||
|
cf0143455f | ||
|
dcd2986b9a | ||
|
86dd178abb | ||
|
e8634abc0d | ||
|
936bfe227a | ||
|
9e5a44ab13 | ||
|
dcbe303b4e | ||
|
b480c5a453 | ||
|
4d73c03fee | ||
|
6d993c7a87 | ||
|
04d8be4573 | ||
|
b9f6401be2 | ||
|
cc40e7fbed | ||
|
ccef5e232c | ||
|
dbcac21087 | ||
|
84046c131e | ||
|
32e9922f48 | ||
|
2047b1871f | ||
|
4df45fb5b6 | ||
|
42f041a02e | ||
|
77816238e5 | ||
|
7ddd7652fe | ||
|
6024c36376 | ||
|
40df882eea | ||
|
d8ac079929 | ||
|
8f101d78fc | ||
|
4c985ca386 | ||
|
0eb0d4e360 | ||
|
7ea3709bee | ||
|
eeb74cca0d | ||
|
9b10786ef0 | ||
|
78ff1d4ab8 | ||
|
63858fb051 | ||
|
b5d0ef5550 | ||
|
14f12f023d | ||
|
8cd8d95e60 | ||
|
bf514fbc47 | ||
|
9fe95831cc | ||
|
1ca2930397 | ||
|
dafb951316 | ||
|
bca8828f8c | ||
|
1b7cf8f8f7 | ||
|
a2bc058063 | ||
|
394c8d0466 | ||
|
ef8b9bb1dd | ||
|
8cf52da304 | ||
|
6b70e9e03b | ||
|
7ed7d5f755 | ||
|
48ed932dee | ||
|
a36d1871ba | ||
|
b47d0359b0 | ||
|
5347593d9d | ||
|
7a75d44eb6 | ||
|
612c7ad6b1 | ||
|
c805c4cc27 | ||
|
e8ff4d6ea3 | ||
|
59f90aad47 | ||
|
175b25c7b8 | ||
|
73c546e192 | ||
|
6662098f48 | ||
|
3452e279d1 | ||
|
061d52e68d | ||
|
b8b83f06f3 | ||
|
102e2bc8c3 | ||
|
91396884a6 | ||
|
afcc3183a9 | ||
|
0f2bf17a51 | ||
|
9f12351164 | ||
|
fd5efd6ce2 | ||
|
9cad1a3d18 | ||
|
514099f471 | ||
|
c7a5799881 | ||
|
462fea3fd1 | ||
|
bc97babd53 | ||
|
2d22276bfd | ||
|
fc09a86e51 | ||
|
7e86d58c61 | ||
|
f6a123667c | ||
|
6885e69187 | ||
|
22595ec88c | ||
|
e89b1f6513 | ||
|
7545fba5e2 | ||
|
185e7b3991 | ||
|
ca85f02c52 | ||
|
ff972a36b0 | ||
|
de2f1f972a | ||
|
8211285a4c | ||
|
920d22ad70 | ||
|
6124f735d4 | ||
|
6eb7028a61 | ||
|
3db6aad219 | ||
|
e3e3304208 | ||
|
c3f1918820 | ||
|
ee5cf66c12 | ||
|
461aee78fc | ||
|
a54cbb723a | ||
|
2ffb6295a1 | ||
|
db80b7df3b | ||
|
641b22adad | ||
|
754e31d69f |
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
||||
.DS_Store
|
||||
*.swp
|
||||
node_modules
|
||||
test/dist/suite-bundle.js
|
||||
|
18
.travis.yml
Normal file
@ -0,0 +1,18 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- '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
@ -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).
|
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2011, Vizzuality
|
||||
Copyright (c) 2015, CartoDB
|
||||
All rights reserved.
|
||||
|
||||
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.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by Vizzuality.
|
||||
4. Neither the name of Vizzuality nor the
|
||||
This product includes software developed by CartoDB.
|
||||
4. Neither the name of CartoDB nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
|
39
Makefile
@ -1,17 +1,25 @@
|
||||
|
||||
UGLIFYJS=./node_modules/.bin/uglifyjs
|
||||
BROWSERIFY=./node_modules/browserify/bin/cmd.js
|
||||
|
||||
JS_CLIENT_FILES= lib/torque/*.js \
|
||||
lib/torque/renderer/*.js \
|
||||
lib/torque/gmaps/*.js \
|
||||
lib/torque/ol/*.js \
|
||||
lib/torque/leaflet/leaflet_tileloader_mixin.js \
|
||||
lib/torque/leaflet/canvas_layer.js \
|
||||
lib/torque/leaflet/torque.js
|
||||
lib/torque/leaflet/torque.js
|
||||
|
||||
all: dist/torque.js
|
||||
all: dist/torque.js dist/torque.full.js add-header
|
||||
|
||||
dist/torque.full.uncompressed.js: dist_folder dist/torque.uncompressed.js
|
||||
$(BROWSERIFY) lib/torque/index.js --standalone torque > dist/torque.full.uncompressed.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)
|
||||
cat $(JS_CLIENT_FILES) > dist/torque.uncompressed.js
|
||||
$(BROWSERIFY) lib/torque/index.js --no-bundle-external --standalone torque > dist/torque.uncompressed.js
|
||||
|
||||
dist/torque.js: dist_folder dist/torque.uncompressed.js
|
||||
$(UGLIFYJS) dist/torque.uncompressed.js > dist/torque.js
|
||||
@ -19,10 +27,31 @@ dist/torque.js: dist_folder dist/torque.uncompressed.js
|
||||
dist_folder:
|
||||
mkdir -p dist
|
||||
|
||||
test_dist_folder:
|
||||
mkdir -p test/dist
|
||||
|
||||
dist: dist_folder dist/torque.js
|
||||
|
||||
clean:
|
||||
clean-results:
|
||||
-@rm test/results/*.png
|
||||
|
||||
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
|
||||
|
||||
.PHONY: clean dist_folder
|
||||
|
||||
|
155
NEWS
@ -1,11 +1,162 @@
|
||||
2.2.XX
|
||||
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
|
||||
- Fix marker fill opacity (#72)
|
||||
|
||||
2.6.0
|
||||
- Published using browserify
|
||||
|
||||
2.5.xx
|
||||
- Added support for several auth_token param
|
||||
- Added support for cdn_url in winshaft provider
|
||||
- Added option to jsonp to set custom callback name
|
||||
- Added no_cdn option to windshaft provider
|
||||
- Added getActivePointsBBox method
|
||||
- Added renderer cache when the map is not animated
|
||||
- Added interaction method
|
||||
- Added stat_tag in the map creation url for windshaft provider
|
||||
- Added invalidate method to L.TorqueLayer
|
||||
|
||||
2.4.01
|
||||
- fixed rectangle anchor and size #42
|
||||
- fixed on method in torque.Event
|
||||
- fixed problem updating steps when sql change in windshaft provider
|
||||
|
||||
2.4.00 - May/22/2014
|
||||
- Changed date parsing for windshaft provider
|
||||
- Optimized tile loading
|
||||
- Fixed cartocss update when windshaft.provider was being used
|
||||
- Fixed windshaft provider with https
|
||||
- Generate cartocss in windshaft provider (#37)
|
||||
- Added zoom animation for leaflet
|
||||
- Added metrics to track memory and time
|
||||
- Pause on zoom
|
||||
- Fixed sprite rendering when line width is a float
|
||||
|
||||
2.3.00 - Feb/24/2014
|
||||
-----
|
||||
- Added 'get attribution' function to Leaflet canvas layer.
|
||||
- Added zIndex support to leaflet torque layer
|
||||
- Added CartoDB Maps API data provider (used by default)
|
||||
- Fixed rendering when CartoCSS had zoom conditions (#27)
|
||||
|
||||
2.2.00 - 26/11/2013
|
||||
2.2.00 - Nov/26/2013
|
||||
-----
|
||||
- added torque cumulative support #21
|
||||
|
||||
|
25
README.md
@ -1,6 +1,8 @@
|
||||
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)
|
||||
|
||||
CartoDB users can use this code right away. Specify your username/tablename and datecolumn to get mapping time immediatley.
|
||||
@ -15,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.
|
||||
|
||||
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
|
||||
|
||||
The simplest way to use a visualization with Torque is...
|
||||
|
||||
<div class="margin20"></div>
|
||||
<div class="code_title">Create a simple Torque visualization</div>
|
||||
``` javascript
|
||||
...
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
</body>
|
||||
...
|
||||
#### Create a simple Torque visualization
|
||||
|
||||
```javascript
|
||||
...
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
...
|
||||
<script>
|
||||
// define the torque layer style using cartocss
|
||||
var CARTOCSS = [
|
||||
'Map {',
|
||||
@ -72,9 +74,10 @@ The simplest way to use a visualization with Torque is...
|
||||
});
|
||||
torqueLayer.addTo(map);
|
||||
torqueLayer.play()
|
||||
</script>
|
||||
</body>
|
||||
```
|
||||
|
||||
<script>
|
||||
```
|
||||
[Grab the complete example source code](https://github.com/CartoDB/torque/blob/master/examples/navy_leaflet.html)
|
||||
<div class="margin20"></div>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 212 B |
Before Width: | Height: | Size: 208 B |
Before Width: | Height: | Size: 335 B |
Before Width: | Height: | Size: 207 B |
Before Width: | Height: | Size: 262 B |
Before Width: | Height: | Size: 262 B |
Before Width: | Height: | Size: 332 B |
Before Width: | Height: | Size: 280 B |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 4.4 KiB |
544
css/jqueryui-smoothness/jquery-ui-1.10.2.custom.css
vendored
@ -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;
|
||||
}
|
1
dist/torque.full.js
vendored
Normal file
39945
dist/torque.full.uncompressed.js
vendored
Normal file
3
dist/torque.js
vendored
BIN
dist/torque.js.gz
vendored
6923
dist/torque.uncompressed.js
vendored
189
doc/API.md
@ -1,189 +0,0 @@
|
||||
|
||||
# Torque API
|
||||
|
||||
Torque provides two kinds of visualizations.
|
||||
|
||||
- static: provides a way to create heatmap like visualizations (note for Andrew: fon). see ``TorqueLayer``
|
||||
- dynamic: animate points over a map (note for Andrew: Navy) see ``TiledTorqueLayer``
|
||||
|
||||
|
||||
depending on the map provider you are using you need to use different layer type. Currently we provide layers for Google Maps and Leaflet.
|
||||
|
||||
## L.TorqueLayer(options)
|
||||
|
||||
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',
|
||||
column : 'date',
|
||||
countby : 'count(cartodb_id)',
|
||||
resolution : 1,
|
||||
steps : 750,
|
||||
pixel_size : 3,
|
||||
blendmode : 'lighter'
|
||||
});
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
##### Provider options
|
||||
| Option | type | Default | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| provider | string | ```sql_api``` | Where is the data coming from? Alternative is 'url_template'|
|
||||
|
||||
##### CartoDB data options
|
||||
| Option | type | Default | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| user | string | ```null``` | CartoDB account name. Found as, accountname.cartodb.com|
|
||||
| table | string | ```null``` | CartoDB table name where data is found |
|
||||
| column | string | ```null``` | CartoDB table's column name where date information is found (for dynamic type torque layer only)|
|
||||
| countby | string | ```null``` | The aggregation method to use for each pixel displayed where multiple data are found. Any valid PostgreSQL aggregate function |
|
||||
|
||||
|
||||
##### Display options
|
||||
| Option | type | Default | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| resolution| numeric | ```2``` | The x and y dimensions of each pixel as returned by the data|
|
||||
| blendmode | boolean | ```source-over``` | The HTML5 Canvas composite operation for when multiple pixels overlap on the canvas |
|
||||
|
||||
##### Time options
|
||||
| Option | type | Default | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| steps | integer | ```100``` | The maximun number of steps to divide the data into for animated renderings |
|
||||
| animationDuration | integer | ```null``` | time in seconds the animation last |
|
||||
|
||||
### Time methods
|
||||
|
||||
| Method | options | returns | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| ```setStep(step)``` | ```time numeric``` | ```this``` | sets the animation to the step indicated by ```step```, must be between 0 and ```steps```|
|
||||
| ```play```| | ```this```| starts the animation
|
||||
| ```stop```| | ```this```| stops the animation and set time to step 0
|
||||
| ```pause```| | ```this```| stops the animation but keep the current time (play enables the animation again)
|
||||
|
||||
|
||||
### 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
|
||||
}
|
||||
```
|
||||
|
||||
## L.TiledTorqueLayer(options)
|
||||
|
||||
One of two core classes for the Torque library - it is used to create a static torque layer with client side filtering.
|
||||
|
||||
##### Provider options
|
||||
| Option | type | Default | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| provider | string | ```sql_api``` | Where is the data coming from? Alternative is 'url_template'|
|
||||
| url | string | ```null``` | Tile template URL for fetching data e.g 'http://host.com/{z}/{x}/{y}.json'|
|
||||
|
||||
##### CartoDB data options (Note to Santana: are these really here?)
|
||||
| Option | type | Default | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| user | string | ```null``` | CartoDB account name. Found as, accountname.cartodb.com|
|
||||
| table | string | ```null``` | CartoDB table name where data is found |
|
||||
| column | string | ```null``` | CartoDB table's column name where date information is found (for dynamic type torque layer only)|
|
||||
| countby | string | ```null``` | The aggregation method to use for each pixel displayed where multiple data are found. Any valid PostgreSQL aggregate function |
|
||||
|
||||
|
||||
##### Display options (Note to Santana: is blendmode here? or above even?)
|
||||
| Option | type | Default | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| resolution| numeric | ```2``` | The x and y dimensions of each pixel as returned by the data|
|
||||
| blendmode | boolean | ```source-over``` | The HTML5 Canvas composite operation for when multiple pixels overlap on the canvas |
|
||||
|
||||
### Filtering options
|
||||
|
||||
| Method | options | returns | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| ```setKey(keys)``` | ```keys numeric/array``` | ```this``` | which data categories to display on the map |
|
||||
| ```setSQL(sql)``` | ```sql string ``` | ```this``` | by default sql torque layer uses is
|
||||
"select * from table", this method changes the sql query torque uses to fetch the data |
|
||||
|
||||
### Style options
|
||||
|
||||
| Method | options | returns | Description |
|
||||
|-----------|:-----------|:----------|:---------------------------------------|
|
||||
| ```setCartoCSS(cartocss)``` | ```cartocss string``` | ```this``` | style the map rendering using client-side cartocss |
|
||||
|
||||
``value`` and ``zoom`` variables can be used. only ``polygon-fill`` and ``polygon-opacity`` properties are supported currently. To see the full list of supported parameters, read the [Torque CartoCSS documentation here](CartoCSS.md).
|
||||
|
||||
TorqueLayer currently expects ```polygon``` styling
|
||||
|
||||
##### CartoCSS Example
|
||||
|
||||
This should be ```string``` encoded in Javascript
|
||||
|
||||
```css
|
||||
#layer {
|
||||
polygon-fill: #FFFF00;
|
||||
[value >= 10] { polygon-fill: #FFCC00; }
|
||||
[value >= 100] { polygon-fill: #FF9900; }
|
||||
[value >= 1000] { polygon-fill: #FF6600; }
|
||||
[value >= 10000] { polygon-fill: #FF3300; }
|
||||
[value > 100000] { polygon-fill: #C00; }
|
||||
}
|
||||
```
|
||||
|
||||
# Google Maps Layers
|
||||
|
||||
## 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.
|
||||
|
||||
|
||||
## GMapsTiledTorqueLayer(options)
|
||||
creates a static _overlay_ to use it with google maps.
|
||||
|
||||
```js
|
||||
var torqueLayer = new torque.GMapsTiledTorqueLayer({
|
||||
provider: 'url_template',
|
||||
url: GBIF_URL,
|
||||
resolution: 4,
|
||||
});
|
||||
|
||||
torqueLayer.setMap(map);
|
||||
|
||||
torqueLayer.setKey([10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]);
|
||||
```
|
||||
|
||||
see ``L.TiledTorqueLayer`` for options reference
|
@ -1,6 +1,6 @@
|
||||
|
||||
<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>
|
||||
#map, html, body {
|
||||
width: 100%; height: 100%; padding: 0; margin: 0;
|
||||
@ -9,10 +9,8 @@
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
|
||||
<script src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
|
||||
<script src="../vendor/underscore.js"></script>
|
||||
<script src="../vendor/carto.js"></script>
|
||||
<script src="../dist/torque.uncompressed.js"></script>
|
||||
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
|
||||
<script src="https://libs.cartocdn.com/torque.js/2.16.5/torque.full.js"></script>
|
||||
|
||||
|
||||
<script>
|
||||
@ -57,7 +55,8 @@
|
||||
steps: 1024,
|
||||
blendmode : 'lighter',
|
||||
animationDuration: 20,
|
||||
map: map
|
||||
map: map,
|
||||
tiler_protocol: 'https'
|
||||
});
|
||||
|
||||
var DEFAULT_CARTOCSS = [
|
99
docs/examples/data_peek.html
Normal 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>
|
||||
|
134
docs/examples/dual_encode.html
Normal 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: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <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>
|
57
docs/examples/examples.json
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
109
docs/examples/leaflet_interaction.html
Normal file
@ -0,0 +1,109 @@
|
||||
|
||||
<html>
|
||||
<style>
|
||||
#map, html, body {
|
||||
width: 100%; height: 100%; padding: 0; margin: 0;
|
||||
}
|
||||
#title {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 50px;
|
||||
color: white;
|
||||
font-size: 27px;
|
||||
font-family: Helvetica, sans-serif;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
<div id="title">Average temperature collected by Britain's Royal Navy (1913-1925)</div>
|
||||
|
||||
<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="../dist/torque.full.uncompressed.js"></script>
|
||||
|
||||
|
||||
<script>
|
||||
// define the torque layer style using cartocss
|
||||
// this creates a kind of density map
|
||||
//color scale from http://colorbrewer2.org/
|
||||
var CARTOCSS = [
|
||||
'Map {',
|
||||
'-torque-time-attribute: "date";',
|
||||
'-torque-aggregation-function: "avg(temp::float)";',
|
||||
'-torque-frame-count: 1;',
|
||||
'-torque-animation-duration: 15;',
|
||||
'-torque-resolution: 16',
|
||||
'}',
|
||||
'#layer {',
|
||||
' marker-width: 8;',
|
||||
' marker-fill-opacity: 1.0;',
|
||||
' marker-fill: #fff5eb; ',
|
||||
' marker-type: rectangle;',
|
||||
' [value > 1] { marker-fill: #fee6ce; }',
|
||||
' [value > 2] { marker-fill: #fdd0a2; }',
|
||||
' [value > 4] { marker-fill: #fdae6b; }',
|
||||
' [value > 10] { marker-fill: #fd8d3c; }',
|
||||
' [value > 15] { marker-fill: #f16913; }',
|
||||
' [value > 20] { marker-fill: #d94801; }',
|
||||
' [value > 25] { marker-fill: #8c2d04; }',
|
||||
'}'
|
||||
].join('\n');
|
||||
|
||||
|
||||
var map = new L.Map('map', {
|
||||
zoomControl: true,
|
||||
center: [40, 0],
|
||||
zoom: 3
|
||||
});
|
||||
|
||||
L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', {
|
||||
attribution: 'CartoDB'
|
||||
}).addTo(map, true);
|
||||
|
||||
var torqueLayer = new L.TorqueLayer({
|
||||
user : 'viz2',
|
||||
table : 'ow',
|
||||
cartocss: CARTOCSS,
|
||||
tiler_protocol: 'https',
|
||||
tiler_port: 443,
|
||||
zIndex: 10
|
||||
});
|
||||
torqueLayer.addTo(map);
|
||||
|
||||
map.on('click', function(e) {
|
||||
var p = e.containerPoint
|
||||
var value = torqueLayer.getValueForPos(p.x, p.y);
|
||||
if (value !== null) {
|
||||
map.openPopup('average temperature: ' + value.value + "C", e.latlng);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// show small rectable and change cursor on hover
|
||||
var hover = null;
|
||||
map.on('mousemove', function(e) {
|
||||
var p = e.containerPoint
|
||||
var value = torqueLayer.getValueForPos(p.x, p.y);
|
||||
|
||||
// remove previous hover box
|
||||
if (hover) {
|
||||
map.removeLayer(hover);
|
||||
hover = null;
|
||||
}
|
||||
|
||||
if (value !== null) {
|
||||
hover = L.rectangle(value.bbox, {
|
||||
color: '#000',
|
||||
weight: 1
|
||||
}).addTo(map);
|
||||
map._container.style.cursor = 'pointer';
|
||||
} else {
|
||||
map._container.style.cursor = 'auto';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
97
docs/examples/light_bright.html
Normal 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: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <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>
|
@ -1,6 +1,4 @@
|
||||
|
||||
<html>
|
||||
<link rel="stylesheet" href="../vendor/leaflet.css" />
|
||||
<style>
|
||||
#map, html, body {
|
||||
width: 100%; height: 100%; padding: 0; margin: 0;
|
||||
@ -10,12 +8,8 @@
|
||||
<div id="map"></div>
|
||||
|
||||
|
||||
<script src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
|
||||
|
||||
<script src="../vendor/underscore.js"></script>
|
||||
<script src="../vendor/carto.js"></script>
|
||||
|
||||
<script src="../dist/torque.js"></script>
|
||||
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
|
||||
<script src="https://libs.cartocdn.com/torque.js/2.16.5/torque.full.js" type="application/javascript" charset="utf-8"></script>
|
||||
|
||||
|
||||
<script>
|
||||
@ -81,9 +75,14 @@
|
||||
user : 'viz2',
|
||||
table : 'ow',
|
||||
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.play()
|
||||
}
|
70
docs/examples/navy_leaflet.html
Normal 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>
|
||||
|
75
docs/examples/navy_ol.html
Normal 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>
|
83
docs/examples/render-range_leaflet.html
Normal 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: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <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>
|
||||
|
94
docs/examples/static_bubble_map.html
Normal 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: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <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>
|
93
docs/examples/static_heat_map.html
Normal 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: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <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>
|
80
docs/examples/static_heat_map_simple.html
Normal 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: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <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>
|
@ -1,6 +1,5 @@
|
||||
|
||||
<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>
|
||||
#map, html, body {
|
||||
width: 100%; height: 100%; padding: 0; margin: 0;
|
||||
@ -9,10 +8,8 @@
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
|
||||
<script src="../vendor/leaflet.js"></script>
|
||||
<script src="../vendor/underscore.js"></script>
|
||||
<script src="../vendor/carto.js"></script>
|
||||
<script src="../dist/torque.uncompressed.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/leaflet.js"></script>
|
||||
<script src="../dist/torque.full.uncompressed.js"></script>
|
||||
|
||||
|
||||
<script>
|
||||
@ -53,10 +50,14 @@
|
||||
}).addTo(map);
|
||||
|
||||
var torqueLayer = new L.TorqueLayer({
|
||||
user : 'viz2',
|
||||
table : 'ow',
|
||||
tileJSON: "http://localhost:4000/examples/tilejson.json",
|
||||
cartocss: CARTOCSS
|
||||
});
|
||||
torqueLayer.error(function(err){
|
||||
for(error in err){
|
||||
console.warn(err[error]);
|
||||
}
|
||||
});
|
||||
torqueLayer.addTo(map);
|
||||
torqueLayer.play()
|
||||
</script>
|
8
docs/examples/tilejson.json
Normal 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"]
|
||||
}
|
77
docs/guides/01-getting-started.md
Normal 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/).
|
24
docs/guides/02-cartocss.md
Normal 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.
|
138
docs/guides/03-torque-interaction-methods.md
Normal 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);
|
||||
}
|
||||
});
|
||||
```
|
60
docs/guides/04-torque-time-slider.md
Normal 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_
|
69
docs/guides/05-how-spatial-aggregation-works.md
Normal 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
@ -0,0 +1 @@
|
||||
|
5
docs/reference/01-introduction.md
Normal 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/)
|
3
docs/reference/02-versioning.md
Normal 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).
|
28
docs/reference/03-L.TorqueLayer.md
Normal 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
|
6
docs/reference/04-using-a-CARTO-table-directly.md
Normal 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```
|
5
docs/reference/05-using-a-custom-SQL-query.md
Normal 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.
|
9
docs/reference/06-providing-a-TileJSON-file.md
Normal 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
|
||||
|
||||
|
14
docs/reference/07-time-methods.md
Normal 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.
|
6
docs/reference/08-layer-control-methods.md
Normal 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
|
33
docs/reference/09-style-methods.md
Normal 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;
|
||||
}
|
||||
```
|
12
docs/reference/10-data-methods.md
Normal 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");
|
28
docs/reference/11-events.md
Normal 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);
|
||||
});
|
||||
```
|
12
docs/reference/12-Google-maps-layers.md
Normal 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
|
36
docs/support/01-support-options.md
Normal 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.
|
36
docs/support/02-contribute.md
Normal 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).
|
@ -1,67 +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/underscore.js"></script>
|
||||
<script src="../vendor/carto.js"></script>
|
||||
<script src="../lib/torque/cartocss_reference.js"></script>
|
||||
<script src="../lib/torque/profiler.js"></script>
|
||||
<script src="../lib/torque/request.js"></script>
|
||||
<script src="../lib/torque/leaflet/leaflet_tileloader_mixin.js"></script>
|
||||
<script src="../lib/torque/leaflet/canvas_layer.js"></script>
|
||||
<script src="../lib/torque/renderer/point.js"></script>
|
||||
<script src="../lib/torque/renderer/rectangle.js"></script>
|
||||
<script src="../lib/torque/provider.json.js"></script>
|
||||
<script src="../lib/torque/provider.jsonarray.js"></script>
|
||||
<script src="../lib/torque/leaflet/torque.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>
|
||||
|
@ -1,158 +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/underscore.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>
|
@ -1,221 +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/underscore.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>
|
@ -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>
|
263
examples/vendor/codemirror.css
vendored
@ -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;
|
||||
}
|
||||
}
|
5887
examples/vendor/codemirror.js
vendored
639
examples/vendor/css.js
vendored
@ -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"
|
||||
});
|
||||
})();
|
94
examples/vendor/dat.gui.min.js
vendored
@ -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>
|
10
index.html
@ -117,10 +117,10 @@
|
||||
|
||||
<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://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
|
||||
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false&v=3.12"></script>
|
||||
<script src="vendor/leaflet.js"></script>
|
||||
<script src="vendor/underscore.js"></script>
|
||||
<script src="vendor/carto.js"></script>
|
||||
<script src="examples/vendor/leaflet.js"></script>
|
||||
<script src="examples/vendor/carto.js"></script>
|
||||
<script src="examples/vendor/codemirror.js"></script>
|
||||
<script src="examples/vendor/css.js"></script>
|
||||
|
||||
@ -148,6 +148,7 @@
|
||||
'countby',
|
||||
'resolution',
|
||||
'steps',
|
||||
'loop',
|
||||
'animationDuration'
|
||||
)
|
||||
}))
|
||||
@ -156,10 +157,12 @@
|
||||
function init_torque(map, options) {
|
||||
// init torque layer
|
||||
torqueLayer = new torque.GMapsTorqueLayer(_.extend({
|
||||
provider: 'sql_api',
|
||||
user : 'viz2',
|
||||
table : 'ow',
|
||||
column : 'date',
|
||||
countby : 'count(cartodb_id)',
|
||||
loop : true,
|
||||
resolution: 1,
|
||||
steps: 800,
|
||||
blendmode : 'lighter',
|
||||
@ -218,6 +221,7 @@
|
||||
torqueLayer.animator.duration(d);
|
||||
saveState();
|
||||
});
|
||||
ui.add(TorqueOptions, 'loop');
|
||||
ui.add({ cartocss_editor: toggle_editor }, 'cartocss_editor');
|
||||
//ui.remember(TorqueOptions);
|
||||
//ui.add(TorqueOptions, 'blendmode', blend_modes);
|
||||
|
28
lib/header.js
Normal 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);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
24
lib/torque/animator-steps-range.js
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* Abstract handler for animator steps
|
||||
*/
|
||||
var AnimatorStepsRange = function(start, end) {
|
||||
if (start < 0) throw new Error('start must be a positive number');
|
||||
if (start >= end) throw new Error('start must be smaller than end');
|
||||
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
};
|
||||
|
||||
AnimatorStepsRange.prototype = {
|
||||
|
||||
diff: function() {
|
||||
return this.end - this.start;
|
||||
},
|
||||
|
||||
isLast: function(step) {
|
||||
// round step into an integer, to be able to compare number as expected (also converts bad input to 0)
|
||||
return (step | 0) === this.end;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = AnimatorStepsRange;
|
@ -1,10 +1,17 @@
|
||||
(function(exports) {
|
||||
var torque = require('./');
|
||||
var AnimatorStepsRange = require('./animator-steps-range');
|
||||
|
||||
exports.torque = exports.torque || {};
|
||||
var requestAnimationFrame = global.requestAnimationFrame
|
||||
|| global.mozRequestAnimationFrame
|
||||
|| global.webkitRequestAnimationFrame
|
||||
|| global.msRequestAnimationFrame
|
||||
|| function(callback) { return global.setTimeout(callback, 1000 / 60); };
|
||||
|
||||
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function(c) { setTimeout(c, 16); }
|
||||
|
||||
var cancelAnimationFrame = window.requestAnimationFrame || window.mozCancelAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function(c) { };
|
||||
var cancelAnimationFrame = global.cancelAnimationFrame
|
||||
|| global.mozCancelAnimationFrame
|
||||
|| global.webkitCancelAnimationFrame
|
||||
|| global.msCancelAnimationFrame
|
||||
|| function(id) { clearTimeout(id); };
|
||||
|
||||
/**
|
||||
* options:
|
||||
@ -21,22 +28,26 @@
|
||||
this._t0 = +new Date();
|
||||
this.callback = callback;
|
||||
this._time = 0.0;
|
||||
_.defaults(this.options, {
|
||||
animationDelay: 0,
|
||||
maxDelta: 0.2,
|
||||
loop: true
|
||||
});
|
||||
this.itemsReady = false;
|
||||
|
||||
this.rescale();
|
||||
this.options = torque.extend({
|
||||
animationDelay: 0,
|
||||
maxDelta: 0.2,
|
||||
loop: options.loop === undefined ? true : options.loop
|
||||
}, this.options);
|
||||
|
||||
this.steps(options.steps);
|
||||
}
|
||||
|
||||
|
||||
Animator.prototype = {
|
||||
|
||||
start: function() {
|
||||
this.running = true;
|
||||
requestAnimationFrame(this._tick);
|
||||
this.running = true;
|
||||
requestAnimationFrame(this._tick);
|
||||
this.options.onStart && this.options.onStart();
|
||||
if (this.stepsRange().diff() === 1) {
|
||||
this.running = false;
|
||||
}
|
||||
},
|
||||
|
||||
isRunning: function() {
|
||||
@ -45,7 +56,8 @@
|
||||
|
||||
stop: function() {
|
||||
this.pause();
|
||||
this.time(0);
|
||||
this.time(this.stepsRange().start);
|
||||
this.options.onStop && this.options.onStop();
|
||||
},
|
||||
|
||||
// real animation time
|
||||
@ -67,9 +79,10 @@
|
||||
rescale: function() {
|
||||
this.domainInv = torque.math.linear(this.options.animationDelay, this.options.animationDelay + this.options.animationDuration);
|
||||
this.domain = this.domainInv.invert();
|
||||
this.range = torque.math.linear(0, this.options.steps);
|
||||
this.range = torque.math.linear(0, this._defaultStepsRange.end);
|
||||
this.rangeInv = this.range.invert();
|
||||
this.time(this._time);
|
||||
this.running? this.start(): this.pause();
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -85,9 +98,34 @@
|
||||
|
||||
steps: function(_) {
|
||||
this.options.steps = _;
|
||||
this._defaultStepsRange = new AnimatorStepsRange(0, _);
|
||||
return this.rescale();
|
||||
},
|
||||
|
||||
// Returns or sets a (custom) steps range
|
||||
// Setting a steps range must be within the full range
|
||||
stepsRange: function(start, end) {
|
||||
if (arguments.length === 2) {
|
||||
if (start < this._defaultStepsRange.start) throw new Error('start must be within default steps range');
|
||||
if (end > this._defaultStepsRange.end) throw new Error('end must be within default steps range');
|
||||
|
||||
this._customStepsRange = new 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) {
|
||||
if(arguments.length === 0) return this.range(this.domain(this._time));
|
||||
this._time = this.domainInv(this.rangeInv(s));
|
||||
@ -96,6 +134,7 @@
|
||||
pause: function() {
|
||||
this.running = false;
|
||||
cancelAnimationFrame(this._tick);
|
||||
this.options.onPause && this.options.onPause();
|
||||
},
|
||||
|
||||
_tick: function() {
|
||||
@ -106,19 +145,23 @@
|
||||
delta = Math.min(this.options.maxDelta, delta);
|
||||
this._t0 = t1;
|
||||
this._time += delta;
|
||||
this.time(this._time);
|
||||
if(this.step() >= this.options.steps) {
|
||||
this._time = 0;
|
||||
|
||||
var stepsRange = this.stepsRange();
|
||||
if (stepsRange.isLast(this.step())) {
|
||||
if(!this.options.loop){
|
||||
// set time to max time
|
||||
this.time(this.options.animationDuration);
|
||||
this.pause();
|
||||
} else {
|
||||
this.step(stepsRange.start);
|
||||
}
|
||||
}
|
||||
if(this.running) {
|
||||
this.time(this._time);
|
||||
requestAnimationFrame(this._tick);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
exports.torque.Animator = Animator;
|
||||
|
||||
|
||||
|
||||
})(typeof exports === "undefined" ? this : exports);
|
||||
module.exports = Animator;
|
||||
|
@ -1,7 +1,3 @@
|
||||
(function(exports) {
|
||||
|
||||
exports.torque = exports.torque || {};
|
||||
|
||||
var _torque_reference_latest = {
|
||||
"version": "1.0.0",
|
||||
"style": {
|
||||
@ -33,6 +29,13 @@ var _torque_reference_latest = {
|
||||
"default-meaning": "No buffer will be used",
|
||||
"doc": "Extra tolerance around the Layer extent (in pixels) used to when querying and (potentially) clipping the layer data during rendering"
|
||||
},
|
||||
"-torque-clear-color": {
|
||||
"css": "-torque-clear-color",
|
||||
"type": "color",
|
||||
"default-value": "rgba(255, 255, 255, 0)",
|
||||
"default-meaning": "full clear",
|
||||
"doc": "color used to clear canvas on each frame"
|
||||
},
|
||||
"-torque-frame-count": {
|
||||
"css": "-torque-frame-count",
|
||||
"default-value": "128",
|
||||
@ -229,6 +232,12 @@ var _torque_reference_latest = {
|
||||
],
|
||||
"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)"
|
||||
},
|
||||
"width": {
|
||||
"css": "marker-width",
|
||||
"default-value": 10,
|
||||
"doc": "The width of the marker, if using one of the default types.",
|
||||
"type": "float"
|
||||
}
|
||||
},
|
||||
"point": {
|
||||
@ -399,11 +408,9 @@ var _torque_reference_latest = {
|
||||
}
|
||||
};
|
||||
|
||||
exports.torque['torque-reference'] = {
|
||||
module.exports = {
|
||||
version: {
|
||||
latest: _torque_reference_latest,
|
||||
'1.0.0': _torque_reference_latest
|
||||
}
|
||||
}
|
||||
|
||||
})(typeof exports === "undefined" ? this : exports);
|
||||
};
|
||||
|
@ -1,8 +1,7 @@
|
||||
//
|
||||
// common functionallity for torque layers
|
||||
//
|
||||
|
||||
(function(exports) {
|
||||
var carto = global.carto || require('carto');
|
||||
|
||||
function TorqueLayer() {}
|
||||
|
||||
@ -37,7 +36,4 @@ TorqueLayer.optionsFromCartoCSS = function(cartocss) {
|
||||
return TorqueLayer.optionsFromLayer(mapConfig);
|
||||
};
|
||||
|
||||
exports.torque.common = torque.common || {};
|
||||
exports.torque.common.TorqueLayer = TorqueLayer;
|
||||
|
||||
})(typeof exports === "undefined" ? this : exports);
|
||||
module.exports.TorqueLayer = TorqueLayer;
|
||||
|
@ -1,12 +1,9 @@
|
||||
(function(exports) {
|
||||
|
||||
exports.torque = exports.torque || {};
|
||||
|
||||
var Event = {};
|
||||
Event.on = function(evt, callback) {
|
||||
var cb = this._evt_callbacks = this._evt_callbacks || {};
|
||||
var l = cb[evt] || (cb[evt] = []);
|
||||
l.push(callback);
|
||||
return this;
|
||||
};
|
||||
|
||||
Event.trigger = function(evt) {
|
||||
@ -14,6 +11,7 @@
|
||||
for(var i = 0; c && i < c.length; ++i) {
|
||||
c[i].apply(this, Array.prototype.slice.call(arguments, 1));
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Event.fire = Event.trigger;
|
||||
@ -29,24 +27,65 @@
|
||||
if(c[i] === callback) remove.push(i);
|
||||
}
|
||||
while((i = remove.pop()) !== undefined) c.splice(i, 1);
|
||||
return this;
|
||||
};
|
||||
|
||||
Event.callbacks = function(evt) {
|
||||
return (this._evt_callbacks && this._evt_callbacks[evt]) || [];
|
||||
};
|
||||
|
||||
exports.torque.Event = Event;
|
||||
function extend() {
|
||||
var objs = arguments;
|
||||
var a = objs[0];
|
||||
for (var i = 1; i < objs.length; ++i) {
|
||||
var b = objs[i];
|
||||
for (var k in b) {
|
||||
a[k] = b[k];
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
function clone(a) {
|
||||
return extend({}, a);
|
||||
}
|
||||
|
||||
function isFunction(f) {
|
||||
return typeof f == 'function' || false;
|
||||
}
|
||||
|
||||
function isArray(value) {
|
||||
return value && typeof value == 'object' && Object.prototype.toString.call(value) == '[object Array]';
|
||||
}
|
||||
|
||||
// types
|
||||
exports.torque.types = {
|
||||
Uint8Array: typeof(window['Uint8Array']) !== 'undefined' ? window.Uint8Array : Array,
|
||||
Uint32Array: typeof(window['Uint32Array']) !== 'undefined' ? window.Uint32Array : Array,
|
||||
Int32Array: typeof(window['Int32Array']) !== 'undefined' ? window.Int32Array: Array
|
||||
var types = {
|
||||
Uint8Array: typeof(global['Uint8Array']) !== 'undefined' ? global.Uint8Array : Array,
|
||||
Uint8ClampedArray: typeof(global['Uint8ClampedArray']) !== 'undefined' ? global.Uint8ClampedArray: 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
|
||||
};
|
||||
|
||||
exports.torque.isBrowserSupported = function() {
|
||||
function isBrowserSupported() {
|
||||
return !!document.createElement('canvas');
|
||||
}
|
||||
|
||||
function userAgent() {
|
||||
return typeof navigator !== 'undefined' ? navigator.userAgent : '';
|
||||
}
|
||||
|
||||
var flags = {
|
||||
sprites_to_images: userAgent().indexOf('Safari') === -1 && userAgent().indexOf('Firefox') === -1
|
||||
};
|
||||
|
||||
})(typeof exports === "undefined" ? this : exports);
|
||||
module.exports = {
|
||||
Event: Event,
|
||||
extend: extend,
|
||||
clone: clone,
|
||||
isFunction: isFunction,
|
||||
isArray: isArray,
|
||||
types: types,
|
||||
isBrowserSupported: isBrowserSupported,
|
||||
flags: flags
|
||||
};
|
||||
|
@ -29,7 +29,6 @@
|
||||
* @param {CanvasLayerOptions=} opt_options Options to set in this CanvasLayer.
|
||||
*/
|
||||
|
||||
if(typeof(google) !== 'undefined' && typeof(google.maps) !== 'undefined') {
|
||||
function CanvasLayer(opt_options) {
|
||||
/**
|
||||
* If true, canvas is in a map pane and the OverlayView is fully functional.
|
||||
@ -288,6 +287,24 @@ CanvasLayer.prototype.setPaneName = function(paneName) {
|
||||
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.
|
||||
*/
|
||||
@ -502,4 +519,5 @@ CanvasLayer.prototype.scheduleUpdate = function() {
|
||||
this.requestAnimFrame_.call(window, this.requestUpdateFunction_);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = CanvasLayer;
|
||||
|
@ -4,8 +4,6 @@
|
||||
====================
|
||||
*/
|
||||
|
||||
if(typeof(google) !== 'undefined' && typeof(google.maps) !== 'undefined') {
|
||||
|
||||
function CanvasTileLayer(canvas_setup, render) {
|
||||
this.tileSize = new google.maps.Size(256, 256);
|
||||
this.maxZoom = 19;
|
||||
@ -95,4 +93,4 @@ CanvasTileLayer.prototype.releaseTile = function (tile) {
|
||||
delete this.tiles[id];
|
||||
};
|
||||
|
||||
}
|
||||
module.exports = CanvasTileLayer;
|
||||
|
@ -1,7 +1,3 @@
|
||||
(function(exports) {
|
||||
|
||||
if(typeof(google) === 'undefined' || typeof(google.maps) === 'undefined') return;
|
||||
|
||||
function GMapsTileLoader() {
|
||||
}
|
||||
|
||||
@ -12,6 +8,7 @@ GMapsTileLoader.prototype = {
|
||||
this._map = map;
|
||||
this._projection = projection;
|
||||
this._tiles = {};
|
||||
this._tilesLoading = {};
|
||||
this._tilesToLoad = 0;
|
||||
this._updateTiles = this._updateTiles.bind(this);
|
||||
this._listeners = [];
|
||||
@ -24,16 +21,17 @@ GMapsTileLoader.prototype = {
|
||||
},
|
||||
|
||||
_removeTileLoader: function() {
|
||||
for(var i in this._listeners) {
|
||||
google.maps.event.removeListener(this._listeners[i]);
|
||||
}
|
||||
this._listeners.forEach(function (listener) {
|
||||
google.maps.event.removeListener(listener);
|
||||
});
|
||||
|
||||
this._removeTiles();
|
||||
},
|
||||
|
||||
_removeTiles: function () {
|
||||
for (var key in this._tiles) {
|
||||
this._removeTile(key);
|
||||
}
|
||||
for (var key in this._tiles) {
|
||||
this._removeTile(key);
|
||||
}
|
||||
},
|
||||
|
||||
_reloadTiles: function() {
|
||||
@ -100,15 +98,23 @@ GMapsTileLoader.prototype = {
|
||||
_removeTile: function (key) {
|
||||
this.onTileRemoved && this.onTileRemoved(this._tiles[key]);
|
||||
delete this._tiles[key];
|
||||
delete this._tilesLoading[key];
|
||||
},
|
||||
|
||||
_tileKey: function(tilePoint) {
|
||||
return tilePoint.x + ':' + tilePoint.y + ':' + tilePoint.zoom;
|
||||
},
|
||||
|
||||
_tileShouldBeLoaded: function (tilePoint) {
|
||||
return !((tilePoint.x + ':' + tilePoint.y + ':' + tilePoint.zoom) in this._tiles);
|
||||
var k = this._tileKey(tilePoint);
|
||||
return !(k in this._tiles) && !(k in this._tilesLoading);
|
||||
},
|
||||
|
||||
_tileLoaded: function(tilePoint, tileData) {
|
||||
this._tilesToLoad--;
|
||||
this._tiles[tilePoint.x + ':' + tilePoint.y + ':' + tilePoint.zoom] = tileData;
|
||||
var k = tilePoint.x + ':' + tilePoint.y + ':' + tilePoint.zoom
|
||||
this._tiles[k] = tileData;
|
||||
delete this._tilesLoading[k];
|
||||
if(this._tilesToLoad === 0) {
|
||||
this.onTilesLoaded && this.onTilesLoaded();
|
||||
}
|
||||
@ -182,15 +188,19 @@ GMapsTileLoader.prototype = {
|
||||
|
||||
this._tilesToLoad += tilesToLoad;
|
||||
|
||||
if (this.onTileAdded) {
|
||||
for (i = 0; i < tilesToLoad; i++) {
|
||||
this.onTileAdded(queue[i]);
|
||||
var t = queue[i];
|
||||
var k = this._tileKey(t);
|
||||
this._tilesLoading[k] = t;
|
||||
// events
|
||||
if (this.onTileAdded) {
|
||||
this.onTileAdded(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.onTilesLoading && this.onTilesLoading();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
torque.GMapsTileLoader = GMapsTileLoader;
|
||||
|
||||
})(typeof exports === "undefined" ? this : exports);
|
||||
module.exports = GMapsTileLoader;
|
||||
|
6
lib/torque/gmaps/index.js
Normal file
@ -0,0 +1,6 @@
|
||||
var gmaps = {};
|
||||
if (typeof google !== 'undefined' && typeof google.maps !== 'undefined') {
|
||||
gmaps = require('./torque');
|
||||
gmaps.GMapsTileLoader = require('./gmaps_tileloader_mixin');
|
||||
}
|
||||
module.exports = gmaps;
|
@ -1,36 +1,60 @@
|
||||
(function(exports) {
|
||||
|
||||
if(typeof(google) === 'undefined' || typeof(google.maps) === 'undefined') return;
|
||||
var carto = global.carto || require('carto');
|
||||
var torque = require('../');
|
||||
var CanvasLayer = require('./CanvasLayer');
|
||||
var CanvasTileLayer = require('./canvas_tile_layer');
|
||||
var GMapsTileLoader = require('./gmaps_tileloader_mixin');
|
||||
|
||||
function GMapsTorqueLayer(options) {
|
||||
var self = this;
|
||||
if (!torque.isBrowserSupported()) {
|
||||
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.ready = false;
|
||||
this.options = _.extend({}, options);
|
||||
_.defaults(this.options, {
|
||||
this.options = torque.extend({}, options);
|
||||
this.options = torque.extend({
|
||||
provider: 'windshaft',
|
||||
renderer: 'point',
|
||||
resolution: 2,
|
||||
steps: 100,
|
||||
visible: true
|
||||
});
|
||||
}, this.options);
|
||||
if (options.cartocss) {
|
||||
_.extend(this.options,
|
||||
torque.extend(this.options,
|
||||
torque.common.TorqueLayer.optionsFromCartoCSS(options.cartocss));
|
||||
}
|
||||
|
||||
if(options.tileJSON) this.options.provider = "tileJSON";
|
||||
|
||||
this.hidden = !this.options.visible;
|
||||
|
||||
this.showLimitErrors = options.showLimitErrors;
|
||||
|
||||
this.animator = new torque.Animator(function(time) {
|
||||
var k = time | 0;
|
||||
if(self.key !== k) {
|
||||
if(self.getKey() !== k) {
|
||||
self.setKey(k);
|
||||
}
|
||||
}, 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.stop = this.animator.stop.bind(this.animator);
|
||||
@ -41,8 +65,6 @@ function GMapsTorqueLayer(options) {
|
||||
|
||||
|
||||
CanvasLayer.call(this, {
|
||||
map: this.options.map,
|
||||
//resizeHandler: this.redraw,
|
||||
animate: false,
|
||||
updateHandler: this.render,
|
||||
readyHandler: this.initialize
|
||||
@ -53,16 +75,17 @@ function GMapsTorqueLayer(options) {
|
||||
/**
|
||||
* torque layer
|
||||
*/
|
||||
GMapsTorqueLayer.prototype = _.extend({},
|
||||
GMapsTorqueLayer.prototype = torque.extend({},
|
||||
CanvasLayer.prototype,
|
||||
torque.GMapsTileLoader.prototype,
|
||||
GMapsTileLoader.prototype,
|
||||
torque.Event,
|
||||
{
|
||||
|
||||
providers: {
|
||||
'sql_api': torque.providers.json,
|
||||
'url_template': torque.providers.jsonarray,
|
||||
'windshaft': torque.providers.windshaft
|
||||
'url_template': torque.providers.JsonArray,
|
||||
'windshaft': torque.providers.windshaft,
|
||||
'tileJSON': torque.providers.tileJSON
|
||||
},
|
||||
|
||||
renderers: {
|
||||
@ -84,18 +107,19 @@ GMapsTorqueLayer.prototype = _.extend({},
|
||||
self.fire('change:steps', {
|
||||
steps: self.provider.getSteps()
|
||||
});
|
||||
self.setKey(self.key);
|
||||
self.setKeys(self.getKeys());
|
||||
};
|
||||
|
||||
this.provider = new this.providers[this.options.provider](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._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();
|
||||
});
|
||||
|
||||
this._initTileLoader(this.options.map, this.getProjection());
|
||||
this._initTileLoader(this.map, this.getProjection());
|
||||
|
||||
if (this.shader) {
|
||||
this.renderer.setShader(this.shader);
|
||||
@ -115,10 +139,14 @@ GMapsTorqueLayer.prototype = _.extend({},
|
||||
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");
|
||||
}
|
||||
@ -154,14 +182,24 @@ GMapsTorqueLayer.prototype = _.extend({},
|
||||
// for each tile shown on the map request the data
|
||||
onTileAdded: function(t) {
|
||||
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
|
||||
if (t.zoom !== self.options.map.getZoom()) return;
|
||||
if (t.zoom !== self.map.getZoom()) return;
|
||||
|
||||
self._tileLoaded(t, tileData);
|
||||
|
||||
if (tileData) {
|
||||
self.redraw();
|
||||
}
|
||||
});
|
||||
|
||||
self.fire('tileLoaded');
|
||||
|
||||
if (error) {
|
||||
self.fire('tileError', error);
|
||||
}
|
||||
}
|
||||
|
||||
this.provider.getTileData(t, t.zoom, callback);
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
@ -178,7 +216,7 @@ GMapsTorqueLayer.prototype = _.extend({},
|
||||
if(this.hidden) return;
|
||||
var t, tile, pos;
|
||||
var canvas = this.canvas;
|
||||
canvas.width = canvas.width;
|
||||
this.renderer.clearCanvas();
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
// renders only a "frame"
|
||||
@ -187,9 +225,20 @@ GMapsTorqueLayer.prototype = _.extend({},
|
||||
if (tile) {
|
||||
pos = this.getTilePos(tile.coord);
|
||||
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) {
|
||||
var positions = [];
|
||||
var tileMax = this.options.resolution * (256/this.options.resolution - 1);
|
||||
for(var t in this._tiles) {
|
||||
var tile = this._tiles[t];
|
||||
positions = positions.concat(this.renderer.getActivePointsBBox(tile, step));
|
||||
}
|
||||
return positions;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -198,14 +247,29 @@ GMapsTorqueLayer.prototype = _.extend({},
|
||||
* accumulated
|
||||
*/
|
||||
setKey: function(key) {
|
||||
this.key = key;
|
||||
this.animator.step(key);
|
||||
this.redraw();
|
||||
this.fire('change:time', { time: this.getTime(), step: this.key });
|
||||
this.setKeys([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.
|
||||
*/
|
||||
setStep: function(time) {
|
||||
@ -215,11 +279,25 @@ GMapsTorqueLayer.prototype = _.extend({},
|
||||
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
|
||||
*
|
||||
* ``step`` should be between 0 and ``steps - 1``
|
||||
* ``step`` should be between 0 and ``steps - 1``
|
||||
*/
|
||||
stepToTime: function(step) {
|
||||
if (!this.provider) return 0;
|
||||
@ -228,8 +306,16 @@ GMapsTorqueLayer.prototype = _.extend({},
|
||||
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.key;
|
||||
return this.getKey();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -237,13 +323,20 @@ GMapsTorqueLayer.prototype = _.extend({},
|
||||
* in the defined column. Date object
|
||||
*/
|
||||
getTime: function() {
|
||||
return this.stepToTime(this.key);
|
||||
return this.stepToTime(this.getKey());
|
||||
},
|
||||
|
||||
/**
|
||||
* set the cartocss for the current renderer
|
||||
*/
|
||||
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);
|
||||
this.shader = shader;
|
||||
if (this.renderer) {
|
||||
@ -252,10 +345,11 @@ GMapsTorqueLayer.prototype = _.extend({},
|
||||
|
||||
// provider options
|
||||
var options = torque.common.TorqueLayer.optionsFromLayer(shader.findLayer({ name: 'Map' }));
|
||||
this.provider && this.provider.setCartoCSS && this.provider.setCartoCSS(cartocss);
|
||||
if(this.provider && this.provider.setOptions(options)) {
|
||||
this._reloadTiles();
|
||||
}
|
||||
_.extend(this.options, options);
|
||||
torque.extend(this.options, options);
|
||||
|
||||
// animator options
|
||||
if (options.animationDuration) {
|
||||
@ -271,10 +365,81 @@ GMapsTorqueLayer.prototype = _.extend({},
|
||||
},
|
||||
|
||||
onRemove: function() {
|
||||
this.fire('remove');
|
||||
CanvasLayer.prototype.onRemove.call(this);
|
||||
this.animator.stop();
|
||||
this._removeTileLoader();
|
||||
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;
|
||||
}
|
||||
|
||||
});
|
||||
@ -282,12 +447,12 @@ GMapsTorqueLayer.prototype = _.extend({},
|
||||
|
||||
|
||||
function GMapsTiledTorqueLayer(options) {
|
||||
this.options = _.extend({}, options);
|
||||
this.options = torque.extend({}, options);
|
||||
CanvasTileLayer.call(this, this._loadTile.bind(this), this.drawTile.bind(this));
|
||||
this.initialize(options);
|
||||
}
|
||||
|
||||
GMapsTiledTorqueLayer.prototype = _.extend({}, CanvasTileLayer.prototype, {
|
||||
GMapsTiledTorqueLayer.prototype = torque.extend({}, CanvasTileLayer.prototype, {
|
||||
|
||||
providers: {
|
||||
'sql_api': torque.providers.json,
|
||||
@ -301,7 +466,7 @@ GMapsTiledTorqueLayer.prototype = _.extend({}, CanvasTileLayer.prototype, {
|
||||
|
||||
initialize: function(options) {
|
||||
var self = this;
|
||||
this.key = 0;
|
||||
this.keys = [0];
|
||||
|
||||
this.options.renderer = this.options.renderer || 'pixel';
|
||||
this.options.provider = this.options.provider || 'sql_api';
|
||||
@ -337,12 +502,12 @@ GMapsTiledTorqueLayer.prototype = _.extend({}, CanvasTileLayer.prototype, {
|
||||
|
||||
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);
|
||||
},
|
||||
|
||||
setKey: function(key) {
|
||||
this.key = key;
|
||||
this.keys = [key];
|
||||
this.redraw();
|
||||
},
|
||||
|
||||
@ -352,11 +517,23 @@ GMapsTiledTorqueLayer.prototype = _.extend({}, CanvasTileLayer.prototype, {
|
||||
setCartoCSS: function(cartocss) {
|
||||
if (!this.renderer) throw new Error('renderer is not valid');
|
||||
return this.renderer.setCartoCSS(cartocss);
|
||||
},
|
||||
|
||||
setStepsRange: function(start, end) {
|
||||
this.animator.stepsRange(start, end);
|
||||
},
|
||||
|
||||
removeStepsRange: function() {
|
||||
this.animator.removeCustomStepsRange();
|
||||
},
|
||||
|
||||
getStepsRange: function() {
|
||||
return this.animator.stepsRange();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
exports.torque.GMapsTiledTorqueLayer = GMapsTiledTorqueLayer;
|
||||
exports.torque.GMapsTorqueLayer = GMapsTorqueLayer;
|
||||
|
||||
})(typeof exports === "undefined" ? this : exports);
|
||||
module.exports = {
|
||||
GMapsTiledTorqueLayer: GMapsTiledTorqueLayer,
|
||||
GMapsTorqueLayer: GMapsTorqueLayer
|
||||
};
|
||||
|
@ -1,6 +1,19 @@
|
||||
module.exports = require('./core');
|
||||
|
||||
if (typeof module !== "undefined") {
|
||||
module.exports = {
|
||||
cartocss_reference: require('./cartocss_reference').torque['torque-reference'],
|
||||
};
|
||||
}
|
||||
module.exports.Animator = require('./animator');
|
||||
module.exports.cartocss_reference = require('./cartocss_reference');
|
||||
module.exports.common = require('./common');
|
||||
module.exports.math = require('./math');
|
||||
module.exports.Mercator = require('./mercator');
|
||||
module.exports.net = require('./request');
|
||||
module.exports.renderer = require('./renderer');
|
||||
module.exports.providers = require('./provider');
|
||||
|
||||
require('./leaflet');
|
||||
|
||||
var gmaps = require('./gmaps');
|
||||
module.exports.GMapsTileLoader = gmaps.GMapsTileLoader;
|
||||
module.exports.GMapsTorqueLayer = gmaps.GMapsTorqueLayer;
|
||||
module.exports.GMapsTiledTorqueLayer = gmaps.GMapsTiledTorqueLayer;
|
||||
|
||||
require('./ol');
|
@ -1,9 +1,10 @@
|
||||
if(typeof(L) !== 'undefined') {
|
||||
require('./leaflet_tileloader_mixin');
|
||||
|
||||
/**
|
||||
* full canvas layer implementation for Leaflet
|
||||
*/
|
||||
|
||||
L.CanvasLayer = L.Class.extend({
|
||||
L.CanvasLayer = L.Layer.extend({
|
||||
|
||||
includes: [L.Mixin.Events, L.Mixin.TileLoader],
|
||||
|
||||
@ -18,7 +19,8 @@ L.CanvasLayer = L.Class.extend({
|
||||
opacity: 1,
|
||||
unloadInvisibleTiles: L.Browser.mobile,
|
||||
updateWhenIdle: L.Browser.mobile,
|
||||
tileLoader: false // installs tile loading events
|
||||
tileLoader: false, // installs tile loading events
|
||||
zoomAnimation: true
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
@ -27,38 +29,73 @@ L.CanvasLayer = L.Class.extend({
|
||||
//this.project = this._project.bind(this);
|
||||
this.render = this.render.bind(this);
|
||||
L.Util.setOptions(this, options);
|
||||
this._canvas = document.createElement('canvas');
|
||||
this._canvas.style.position = 'absolute';
|
||||
this._canvas.style.top = 0;
|
||||
this._canvas.style.left = 0;
|
||||
this._canvas.style.zIndex = options.zIndex || 0;
|
||||
|
||||
this._canvas = this._createCanvas();
|
||||
// backCanvas for zoom animation
|
||||
if (this.options.zoomAnimation) {
|
||||
this._backCanvas = this._createCanvas();
|
||||
}
|
||||
this._ctx = this._canvas.getContext('2d');
|
||||
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
|
||||
this.currentAnimationFrame = -1;
|
||||
this.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
|
||||
return window.setTimeout(callback, 1000 / 60);
|
||||
};
|
||||
this.requestAnimationFrame = requestAnimationFrame;
|
||||
this.cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame ||
|
||||
window.webkitCancelAnimationFrame || window.msCancelAnimationFrame || function(id) { clearTimeout(id); };
|
||||
},
|
||||
|
||||
_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;
|
||||
var className = 'leaflet-tile-container';
|
||||
if (this.options.zoomAnimation) {
|
||||
className += ' leaflet-zoom-animated';
|
||||
}
|
||||
canvas.setAttribute('class', className);
|
||||
return canvas;
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
this._map = map;
|
||||
|
||||
//this._staticPane = map._createPane('leaflet-tile-pane', map._container);
|
||||
if (!map._panes.staticPane) {
|
||||
map._panes.staticPane = map._createPane('leaflet-tile-pane', map._container);
|
||||
// add container with the canvas to the tile pane
|
||||
// the container is moved in the oposite direction of the
|
||||
// map pane to keep the canvas always in (0, 0)
|
||||
var tilePane = this._map._panes.tilePane;
|
||||
var _container = L.DomUtil.create('div', 'leaflet-layer');
|
||||
_container.appendChild(this._canvas);
|
||||
if (this.options.zoomAnimation) {
|
||||
_container.appendChild(this._backCanvas);
|
||||
this._backCanvas.style.display = 'none';
|
||||
}
|
||||
this._staticPane = map._panes.staticPane
|
||||
this._staticPane.appendChild(this._canvas);
|
||||
tilePane.appendChild(_container);
|
||||
|
||||
map.on({
|
||||
'viewreset': this._reset
|
||||
//'move': this._render
|
||||
this._container = _container;
|
||||
|
||||
// hack: listen to predrag event launched by dragging to
|
||||
// set container in position (0, 0) in screen coordinates
|
||||
map.dragging._draggable.on('predrag', function() {
|
||||
var d = map.dragging._draggable;
|
||||
L.DomUtil.setPosition(this._canvas, { x: -d._newPos.x, y: -d._newPos.y });
|
||||
}, this);
|
||||
|
||||
map.on('move', this._render, this);//function(){ console.log("a"); }, this);
|
||||
map.on({ 'viewreset': this._reset }, this);
|
||||
map.on('move', this.redraw, this);
|
||||
map.on('resize', this._reset, this);
|
||||
|
||||
if (this.options.zoomAnimation) {
|
||||
map.on({
|
||||
'zoomanim': this._animateZoom,
|
||||
'zoomend': this._endZoomAnim,
|
||||
'moveend': this._reset
|
||||
}, this);
|
||||
}
|
||||
|
||||
if(this.options.tileLoader) {
|
||||
this._initTileLoader();
|
||||
}
|
||||
@ -66,6 +103,48 @@ L.CanvasLayer = L.Class.extend({
|
||||
this._reset();
|
||||
},
|
||||
|
||||
_animateZoom: function (e) {
|
||||
if (!this._animating) {
|
||||
this._animating = true;
|
||||
}
|
||||
var back = this._backCanvas;
|
||||
|
||||
back.width = this._canvas.width;
|
||||
back.height = this._canvas.height;
|
||||
|
||||
// paint current canvas in back canvas with trasnformation
|
||||
var pos = this._canvas._leaflet_pos || { x: 0, y: 0 };
|
||||
back.getContext('2d').drawImage(this._canvas, 0, 0);
|
||||
|
||||
L.DomUtil.setPosition(back, L.DomUtil.getPosition(this._canvas));
|
||||
|
||||
// hide original
|
||||
this._canvas.style.display = 'none';
|
||||
back.style.display = 'block';
|
||||
var map = this._map;
|
||||
var scale = map.getZoomScale(e.zoom);
|
||||
var newCenter = map._latLngToNewLayerPoint(map.getCenter(), e.zoom, e.center);
|
||||
var oldCenter = map._latLngToNewLayerPoint(e.center, e.zoom, e.center);
|
||||
|
||||
var origin = {
|
||||
x: newCenter.x - oldCenter.x + pos.x,
|
||||
y: newCenter.y - oldCenter.y + pos.y
|
||||
};
|
||||
|
||||
var bg = back;
|
||||
var transform = L.DomUtil.TRANSFORM;
|
||||
setTimeout(function() {
|
||||
bg.style[transform] = 'translate(' + origin.x + 'px, ' + origin.y + 'px) scale(' + e.scale + ') ';
|
||||
}, 0)
|
||||
},
|
||||
|
||||
_endZoomAnim: function () {
|
||||
this._animating = false;
|
||||
this._canvas.style.display = 'block';
|
||||
this._backCanvas.style.display = 'none';
|
||||
this._backCanvas.style[L.DomUtil.TRANSFORM] = '';
|
||||
},
|
||||
|
||||
getCanvas: function() {
|
||||
return this._canvas;
|
||||
},
|
||||
@ -79,11 +158,14 @@ L.CanvasLayer = L.Class.extend({
|
||||
},
|
||||
|
||||
onRemove: function (map) {
|
||||
this._staticPane.removeChild(this._canvas);
|
||||
this._container.parentNode.removeChild(this._container);
|
||||
map.off({
|
||||
'viewreset': this._reset,
|
||||
'move': this._render,
|
||||
'resize': this._reset
|
||||
'viewreset': this._reset,
|
||||
'move': this.redraw,
|
||||
'moveend': this._reset,
|
||||
'resize': this._reset,
|
||||
'zoomanim': this._animateZoom,
|
||||
'zoomend': this._endZoomAnim
|
||||
}, this);
|
||||
},
|
||||
|
||||
@ -92,6 +174,11 @@ L.CanvasLayer = L.Class.extend({
|
||||
return this;
|
||||
},
|
||||
|
||||
error: function (callback) {
|
||||
this.provider.options.errorCallback = callback;
|
||||
return this;
|
||||
},
|
||||
|
||||
setOpacity: function (opacity) {
|
||||
this.options.opacity = opacity;
|
||||
this._updateOpacity();
|
||||
@ -99,7 +186,12 @@ L.CanvasLayer = L.Class.extend({
|
||||
},
|
||||
|
||||
setZIndex: function(zIndex) {
|
||||
zIndex = zIndex !== void 0 ? zIndex : 1;
|
||||
this._container.style.zIndex = zIndex;
|
||||
this._canvas.style.zIndex = zIndex;
|
||||
if (this.options.zoomAnimation) {
|
||||
this._backCanvas.style.zIndex = zIndex;
|
||||
}
|
||||
},
|
||||
|
||||
bringToFront: function () {
|
||||
@ -114,6 +206,12 @@ L.CanvasLayer = L.Class.extend({
|
||||
var size = this._map.getSize();
|
||||
this._canvas.width = size.x;
|
||||
this._canvas.height = size.y;
|
||||
|
||||
// fix position
|
||||
var pos = L.DomUtil.getPosition(this._map.getPanes().mapPane);
|
||||
if (pos) {
|
||||
L.DomUtil.setPosition(this._canvas, { x: -pos.x, y: -pos.y });
|
||||
}
|
||||
this.onResize();
|
||||
this._render();
|
||||
},
|
||||
@ -128,11 +226,23 @@ L.CanvasLayer = L.Class.extend({
|
||||
_updateOpacity: function () { },
|
||||
|
||||
_render: function() {
|
||||
this.requestAnimationFrame.call(window, this.render);
|
||||
if (this.currentAnimationFrame >= 0) {
|
||||
this.cancelAnimationFrame.call(window, this.currentAnimationFrame);
|
||||
}
|
||||
this.currentAnimationFrame = this.requestAnimationFrame.call(window, this.render);
|
||||
},
|
||||
|
||||
redraw: function() {
|
||||
this._render();
|
||||
// use direct: true if you are inside an animation frame call
|
||||
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) {
|
||||
this.render();
|
||||
} else {
|
||||
this._render();
|
||||
}
|
||||
},
|
||||
|
||||
onResize: function() {
|
||||
@ -143,5 +253,3 @@ L.CanvasLayer = L.Class.extend({
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
} //L defined
|
||||
|
3
lib/torque/leaflet/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
if (typeof L !== 'undefined') {
|
||||
require('./torque');
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
if(typeof(L) !== 'undefined') {
|
||||
|
||||
L.Mixin.TileLoader = {
|
||||
|
||||
_initTileLoader: function() {
|
||||
this._tiles = {}
|
||||
this._tilesLoading = {};
|
||||
this._tilesToLoad = 0;
|
||||
this._map.on({
|
||||
'moveend': this._updateTiles
|
||||
@ -77,15 +75,23 @@ L.Mixin.TileLoader = {
|
||||
_removeTile: function (key) {
|
||||
this.fire('tileRemoved', this._tiles[key]);
|
||||
delete this._tiles[key];
|
||||
delete this._tilesLoading[key];
|
||||
},
|
||||
|
||||
_tileKey: function(tilePoint) {
|
||||
return tilePoint.x + ':' + tilePoint.y + ':' + tilePoint.zoom;
|
||||
},
|
||||
|
||||
_tileShouldBeLoaded: function (tilePoint) {
|
||||
return !((tilePoint.x + ':' + tilePoint.y + ':' + tilePoint.zoom) in this._tiles);
|
||||
var k = this._tileKey(tilePoint);
|
||||
return !(k in this._tiles) && !(k in this._tilesLoading);
|
||||
},
|
||||
|
||||
_tileLoaded: function(tilePoint, tileData) {
|
||||
this._tilesToLoad--;
|
||||
this._tiles[tilePoint.x + ':' + tilePoint.y + ':' + tilePoint.zoom] = tileData;
|
||||
var k = tilePoint.x + ':' + tilePoint.y + ':' + tilePoint.zoom
|
||||
this._tiles[k] = tileData;
|
||||
delete this._tilesLoading[k];
|
||||
if(this._tilesToLoad === 0) {
|
||||
this.fire("tilesLoaded");
|
||||
}
|
||||
@ -93,7 +99,7 @@ L.Mixin.TileLoader = {
|
||||
|
||||
getTilePos: function (tilePoint) {
|
||||
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;
|
||||
|
||||
return tilePoint.multiplyBy(tileSize).subtract(origin);
|
||||
@ -104,6 +110,8 @@ L.Mixin.TileLoader = {
|
||||
center = bounds.getCenter(),
|
||||
zoom = this._map.getZoom();
|
||||
|
||||
zoom = Math.round(zoom);
|
||||
|
||||
var j, i, point;
|
||||
|
||||
for (j = bounds.min.y; j <= bounds.max.y; j++) {
|
||||
@ -129,10 +137,13 @@ L.Mixin.TileLoader = {
|
||||
this._tilesToLoad += tilesToLoad;
|
||||
|
||||
for (i = 0; i < tilesToLoad; i++) {
|
||||
this.fire('tileAdded', queue[i]);
|
||||
var t = queue[i];
|
||||
var k = this._tileKey(t);
|
||||
this._tilesLoading[k] = t;
|
||||
this.fire('tileAdded', t);
|
||||
}
|
||||
this.fire("tilesLoading");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} //L defined
|
||||
}
|
||||
|
@ -1,4 +1,8 @@
|
||||
if(typeof(L) !== 'undefined') {
|
||||
var carto = global.carto || require('carto');
|
||||
var torque = require('../');
|
||||
|
||||
require('./canvas_layer');
|
||||
|
||||
/**
|
||||
* torque layer
|
||||
*/
|
||||
@ -6,8 +10,9 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
|
||||
providers: {
|
||||
'sql_api': torque.providers.json,
|
||||
'url_template': torque.providers.jsonarray,
|
||||
'windshaft': torque.providers.windshaft
|
||||
'url_template': torque.providers.JsonArray,
|
||||
'windshaft': torque.providers.windshaft,
|
||||
'tileJSON': torque.providers.tileJSON
|
||||
},
|
||||
|
||||
renderers: {
|
||||
@ -21,9 +26,18 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
throw new Error("browser is not supported by torque");
|
||||
}
|
||||
options.tileLoader = true;
|
||||
this.key = 0;
|
||||
this.keys = [0];
|
||||
this._tiles = {};
|
||||
Object.defineProperty(this, 'key', {
|
||||
get: function() {
|
||||
return this.getKey();
|
||||
}
|
||||
});
|
||||
this.prevRenderedKey = 0;
|
||||
if (options.cartocss) {
|
||||
_.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;
|
||||
@ -33,10 +47,23 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
|
||||
this.animator = new torque.Animator(function(time) {
|
||||
var k = time | 0;
|
||||
if(self.key !== k) {
|
||||
self.setKey(k);
|
||||
if(self.getKey() !== k) {
|
||||
self.setKey(k, { direct: true });
|
||||
}
|
||||
}, options);
|
||||
}, 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);
|
||||
@ -45,12 +72,20 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
this.setDuration = this.animator.duration.bind(this.animator);
|
||||
this.isRunning = this.animator.isRunning.bind(this.animator);
|
||||
|
||||
|
||||
L.CanvasLayer.prototype.initialize.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.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() {
|
||||
self.fire("change:bounds", {
|
||||
bounds: self.provider.getBounds()
|
||||
@ -60,47 +95,92 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
self.fire('change:steps', {
|
||||
steps: self.provider.getSteps()
|
||||
});
|
||||
self.setKey(self.key);
|
||||
self.setKeys(self.getKeys());
|
||||
};
|
||||
|
||||
this.provider = new this.providers[this.options.provider](options);
|
||||
this.renderer = new this.renderers[this.options.renderer](this.getCanvas(), options);
|
||||
this.on('tileLoaded', function () {
|
||||
self.renderer.setCartoCSS(self.renderer.style);
|
||||
})
|
||||
|
||||
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) {
|
||||
var callback = function (tileData, error) {
|
||||
// don't load tiles that are not being shown
|
||||
if (t.zoom !== self._map.getZoom()) return;
|
||||
|
||||
self._tileLoaded(t, tileData);
|
||||
self._clearTileCaches();
|
||||
|
||||
if (tileData) {
|
||||
self.redraw();
|
||||
}
|
||||
});
|
||||
|
||||
self.fire('tileLoaded');
|
||||
|
||||
if (error) {
|
||||
self.fire('tileError', error);
|
||||
}
|
||||
};
|
||||
|
||||
var tileData = this.provider.getTileData(t, t.zoom, callback);
|
||||
}, this);
|
||||
},
|
||||
|
||||
|
||||
_clearTileCaches: function() {
|
||||
var t, tile;
|
||||
for(t in this._tiles) {
|
||||
tile = this._tiles[t];
|
||||
if (tile && tile._tileCache) {
|
||||
tile._tileCache = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_clearCaches: function() {
|
||||
this.renderer && this.renderer.clearSpriteCache();
|
||||
this._clearTileCaches();
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
map.on({
|
||||
'zoomend': this._clearCaches
|
||||
'zoomend': this._clearCaches,
|
||||
'zoomstart': this._pauseOnZoom
|
||||
}, this);
|
||||
|
||||
map.on({
|
||||
'zoomend': this._resumeOnZoom
|
||||
}, this);
|
||||
L.CanvasLayer.prototype.onAdd.call(this, map);
|
||||
},
|
||||
|
||||
onRemove: function(map) {
|
||||
this.fire('remove');
|
||||
this._removeTileLoader();
|
||||
map.off({
|
||||
'zoomend': this._clearCaches
|
||||
'zoomend': this._clearCaches,
|
||||
'zoomstart': this._pauseOnZoom
|
||||
}, this);
|
||||
map.off({
|
||||
'zoomend': this._resumeOnZoom
|
||||
}, this);
|
||||
L.CanvasLayer.prototype.onRemove.call(this, map);
|
||||
},
|
||||
|
||||
_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();
|
||||
@ -113,10 +193,14 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
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");
|
||||
}
|
||||
@ -158,17 +242,55 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
if(this.hidden) return;
|
||||
var t, tile, pos;
|
||||
var canvas = this.getCanvas();
|
||||
canvas.width = canvas.width;
|
||||
this.renderer.clearCanvas();
|
||||
var ctx = canvas.getContext('2d');
|
||||
|
||||
for(t in this._tiles) {
|
||||
tile = this._tiles[t];
|
||||
if (tile) {
|
||||
// clear cache
|
||||
if (this.animator.isRunning()) {
|
||||
tile._tileCache = null;
|
||||
}
|
||||
|
||||
pos = this.getTilePos(tile.coord);
|
||||
ctx.setTransform(1, 0, 0, 1, pos.x, pos.y);
|
||||
this.renderer.renderTile(tile, this.key, pos.x, pos.y);
|
||||
|
||||
if (tile._tileCache) {
|
||||
// when the tile has a cached image just render it and avoid to render
|
||||
// all the points
|
||||
this.renderer._ctx.drawImage(tile._tileCache, 0, 0);
|
||||
} else {
|
||||
this.renderer.renderTile(tile, this.keys);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.renderer.applyFilters();
|
||||
|
||||
// prepare caches if the animation is not running
|
||||
// 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
|
||||
if (!this.animator.isRunning() && this.getKey() === this.prevRenderedKey) {
|
||||
var tile_size = this.renderer.TILE_SIZE;
|
||||
for(t in this._tiles) {
|
||||
tile = this._tiles[t];
|
||||
if (tile && !tile._tileCache) {
|
||||
var c = tile._tileCache = document.createElement('canvas');
|
||||
c.width = c.height = tile_size;
|
||||
pos = this.getTilePos(tile.coord);
|
||||
// clip bounds, firefox raise an exception when try to get data from outside canvas
|
||||
var x = Math.max(0, pos.x)
|
||||
var y = Math.max(0, pos.y)
|
||||
var w = Math.min(tile_size, this.getCanvas().width - x);
|
||||
var h = Math.min(tile_size, this.getCanvas().height - y);
|
||||
if (w > 0 && h > 0) {
|
||||
c.getContext('2d').drawImage(this.getCanvas(), x, y, w, h, x - pos.x, y - pos.y, w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.prevRenderedKey = this.getKey();
|
||||
|
||||
},
|
||||
|
||||
@ -177,15 +299,40 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
* it renders directly, if it's an array it renders
|
||||
* accumulated
|
||||
*/
|
||||
setKey: function(key) {
|
||||
this.key = key;
|
||||
this.animator.step(key);
|
||||
this.redraw();
|
||||
this.fire('change:time', { time: this.getTime(), step: this.key });
|
||||
setKey: function(key, options) {
|
||||
this.setKeys([key], options);
|
||||
},
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
setStep: function(time) {
|
||||
@ -195,11 +342,25 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
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
|
||||
*
|
||||
* ``step`` should be between 0 and ``steps - 1``
|
||||
* ``step`` should be between 0 and ``steps - 1``
|
||||
*/
|
||||
stepToTime: function(step) {
|
||||
var times = this.provider.getKeySpan();
|
||||
@ -207,8 +368,16 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
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.key;
|
||||
return this.getKey();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -216,14 +385,14 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
* in the defined column. Date object
|
||||
*/
|
||||
getTime: function() {
|
||||
return this.stepToTime(this.key);
|
||||
return this.stepToTime(this.getKey());
|
||||
},
|
||||
|
||||
/**
|
||||
* returns an object with the start and end times
|
||||
*/
|
||||
getTimeSpan: function() {
|
||||
var times = this.provider.getKeySpan();
|
||||
return this.provider.getKeySpan();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -231,107 +400,132 @@ L.TorqueLayer = L.CanvasLayer.extend({
|
||||
*/
|
||||
setCartoCSS: function(cartocss) {
|
||||
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' }));
|
||||
if(this.provider.setOptions(options)) {
|
||||
this._reloadTiles();
|
||||
}
|
||||
_.extend(this.options, options);
|
||||
|
||||
// animator options
|
||||
if (options.animationDuration) {
|
||||
this.animator.duration(options.animationDuration);
|
||||
if (this.provider && this.provider.options.named_map) {
|
||||
console.log('Torque layer: CartoCSS style on named maps is read-only');
|
||||
return false;
|
||||
}
|
||||
|
||||
this.redraw();
|
||||
return this;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
});
|
||||
torque.extend(this.options, options);
|
||||
|
||||
// animator options
|
||||
if (options.animationDuration) {
|
||||
this.animator.duration(options.animationDuration);
|
||||
}
|
||||
this._clearCaches();
|
||||
this.redraw();
|
||||
return this;
|
||||
}.bind(this));
|
||||
|
||||
L.TiledTorqueLayer = L.TileLayer.Canvas.extend({
|
||||
|
||||
providers: {
|
||||
'sql_api': torque.providers.json,
|
||||
'url_template': torque.providers.JsonArray
|
||||
},
|
||||
|
||||
renderers: {
|
||||
'point': torque.renderer.Point,
|
||||
'pixel': torque.renderer.Rectangle
|
||||
},
|
||||
|
||||
initialize: function(options) {
|
||||
var self = this;
|
||||
this.key = 0;
|
||||
|
||||
options.async = true;
|
||||
L.TileLayer.Canvas.prototype.initialize.call(this, options);
|
||||
|
||||
|
||||
this.options.renderer = this.options.renderer || 'pixel';
|
||||
this.options.provider = this.options.provider || 'sql_api';
|
||||
|
||||
this.provider = new this.providers[this.options.provider](options);
|
||||
this.renderer = new this.renderers[this.options.renderer](null, options);
|
||||
|
||||
},
|
||||
|
||||
_tileLoaded: function(tile, tilePoint, tileData) {
|
||||
if(this._tiles[tilePoint.x + ':' + tilePoint.y] !== undefined) {
|
||||
this._tiles[tilePoint.x + ':' + tilePoint.y].data = tileData;
|
||||
this.drawTile(tile);
|
||||
}
|
||||
L.TileLayer.Canvas.prototype._tileLoaded.call(this);
|
||||
},
|
||||
|
||||
redraw: function() {
|
||||
for (var i in this._tiles) {
|
||||
this._redrawTile(this._tiles[i]);
|
||||
}
|
||||
},
|
||||
|
||||
_loadTile: function(tile, tilePoint) {
|
||||
var self = this;
|
||||
L.TileLayer.Canvas.prototype._loadTile.apply(this, arguments);
|
||||
|
||||
// get the data from adjusted point but render in the right canvas
|
||||
var adjusted = tilePoint.clone()
|
||||
this._adjustTilePoint(adjusted);
|
||||
this.provider.getTileData(adjusted, this._map.getZoom(), function(tileData) {
|
||||
self._tileLoaded(tile, tilePoint, tileData);
|
||||
L.DomUtil.addClass(tile, 'leaflet-tile-loaded');
|
||||
});
|
||||
},
|
||||
|
||||
drawTile: function (tile) {
|
||||
var canvas = tile;
|
||||
if(!tile.data) return;
|
||||
canvas.width = canvas.width;
|
||||
|
||||
this.renderer.setCanvas(canvas);
|
||||
|
||||
var accum = this.renderer.accumulate(tile.data, this.key);
|
||||
this.renderer.renderTileAccum(accum, 0, 0);
|
||||
},
|
||||
|
||||
setKey: function(key) {
|
||||
this.key = key;
|
||||
this.redraw();
|
||||
},
|
||||
|
||||
/**
|
||||
* set the cartocss for the current renderer
|
||||
* get active points for a step in active zoom
|
||||
* returns a list of bounding boxes [[] , [], []]
|
||||
* empty list if there is no active pixels
|
||||
*/
|
||||
setCartoCSS: function(cartocss) {
|
||||
if (!this.renderer) throw new Error('renderer is not valid');
|
||||
return this.renderer.setCartoCSS(cartocss);
|
||||
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();
|
||||
},
|
||||
|
||||
onRemove: function(map) {
|
||||
L.CanvasLayer.prototype.onRemove.apply(this, arguments);
|
||||
this.animator.stop();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
} //L defined
|
||||
|
@ -1,7 +1,3 @@
|
||||
(function(exports) {
|
||||
|
||||
exports.torque = exports.torque || {};
|
||||
|
||||
function clamp(a, b) {
|
||||
return function(t) {
|
||||
return Math.max(Math.min(t, b), a);
|
||||
@ -28,11 +24,8 @@
|
||||
return _linear;
|
||||
}
|
||||
|
||||
exports.torque.math = {
|
||||
module.exports = {
|
||||
clamp: clamp,
|
||||
linear: linear,
|
||||
invLinear: invLinear
|
||||
};
|
||||
|
||||
})(typeof exports === "undefined" ? this : exports);
|
||||
|
||||
};
|
||||
|
91
lib/torque/mercator.js
Normal file
@ -0,0 +1,91 @@
|
||||
var Point = function(x, y) {
|
||||
this.x = x || 0;
|
||||
this.y = y || 0;
|
||||
};
|
||||
|
||||
function clamp(value, optMin, optMax) {
|
||||
if (optMin !== null) value = Math.max(value, optMin);
|
||||
if (optMax !== null) value = Math.min(value, optMax);
|
||||
return value;
|
||||
}
|
||||
|
||||
function degreesToRadians(deg) {
|
||||
return deg * (Math.PI / 180);
|
||||
}
|
||||
|
||||
function radiansToDegrees(rad) {
|
||||
return rad / (Math.PI / 180);
|
||||
}
|
||||
|
||||
|
||||
var MercatorProjection = function() {
|
||||
// this._tileSize = L.Browser.retina ? 512 : 256;
|
||||
this._tileSize = 256;
|
||||
this._pixelOrigin = new Point(this._tileSize / 2, this._tileSize / 2);
|
||||
this._pixelsPerLonDegree = this._tileSize / 360;
|
||||
this._pixelsPerLonRadian = this._tileSize / (2 * Math.PI);
|
||||
};
|
||||
|
||||
MercatorProjection.prototype._fromLatLonToPoint = function(lat, lon) {
|
||||
var point = new Point(0, 0);
|
||||
var origin = this._pixelOrigin;
|
||||
|
||||
point.x = origin.x + lon * this._pixelsPerLonDegree;
|
||||
|
||||
// NOTE(appleton): Truncating to 0.9999 effectively limits latitude to
|
||||
// 89.189. This is about a third of a tile past the edge of the world
|
||||
// tile.
|
||||
var siny = clamp(Math.sin(degreesToRadians(lat)), -0.9999, 0.9999);
|
||||
point.y = origin.y + 0.5 * Math.log((1 + siny) / (1 - siny)) * -this._pixelsPerLonRadian;
|
||||
return point;
|
||||
};
|
||||
|
||||
MercatorProjection.prototype._fromPointToLatLon = function(point) {
|
||||
var me = this;
|
||||
var origin = me._pixelOrigin;
|
||||
var lon = (point.x - origin.x) / me._pixelsPerLonDegree;
|
||||
var latRadians = (point.y - origin.y) / -me._pixelsPerLonRadian;
|
||||
var lat = radiansToDegrees(2 * Math.atan(Math.exp(latRadians)) - Math.PI / 2);
|
||||
return { lat:lat, lon:lon };
|
||||
};
|
||||
|
||||
MercatorProjection.prototype._tilePixelPos = function(tileX, tileY) {
|
||||
return {
|
||||
x: tileX*this._tileSize,
|
||||
y: tileY*this._tileSize
|
||||
};
|
||||
};
|
||||
|
||||
MercatorProjection.prototype.tilePixelBBox = function(x, y, zoom, px, py, res) {
|
||||
res = res || 1.0;
|
||||
var numTiles = 1 <<zoom;
|
||||
var inc = res/numTiles;
|
||||
px = (x*this._tileSize + px)/numTiles;
|
||||
py = (y*this._tileSize + py)/numTiles;
|
||||
return [
|
||||
this._fromPointToLatLon(new Point(px, py + inc)),
|
||||
this._fromPointToLatLon(new Point(px + inc, py))
|
||||
];
|
||||
};
|
||||
|
||||
MercatorProjection.prototype.tileBBox = function(x, y, zoom, bufferSize) {
|
||||
var numTiles = 1 <<zoom;
|
||||
bufferSize = bufferSize || 0;
|
||||
var inc = (this._tileSize + bufferSize*2)/numTiles;
|
||||
var px = (x*this._tileSize - bufferSize )/numTiles;
|
||||
var py = (y*this._tileSize - bufferSize )/numTiles;
|
||||
return [
|
||||
this._fromPointToLatLon(new Point(px, py + inc)),
|
||||
this._fromPointToLatLon(new Point(px + inc, py))
|
||||
];
|
||||
};
|
||||
|
||||
MercatorProjection.prototype.latLonToTilePoint = function(lat, lon, tileX, tileY, zoom) {
|
||||
var numTiles = 1 <<zoom;
|
||||
var worldCoordinate = this._fromLatLonToPoint(lat, lon);
|
||||
var pixelCoordinate = new Point(worldCoordinate.x*numTiles, worldCoordinate.y*numTiles);
|
||||
var tilePixelPos = this._tilePixelPos(tileX, tileY);
|
||||
return new Point(Math.round(pixelCoordinate.x-tilePixelPos.x), Math.round(pixelCoordinate.y-tilePixelPos.y));
|
||||
};
|
||||
|
||||
module.exports = MercatorProjection;
|
131
lib/torque/ol/canvas_layer.js
Normal 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
@ -0,0 +1,3 @@
|
||||
if (typeof ol !== 'undefined') {
|
||||
require('./torque');
|
||||
}
|
169
lib/torque/ol/ol_tileloader_mixin.js
Normal 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
@ -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;
|
@ -28,8 +28,6 @@
|
||||
}
|
||||
```
|
||||
*/
|
||||
(function(exports) {
|
||||
|
||||
var MAX_HISTORY = 1024;
|
||||
function Profiler() {}
|
||||
Profiler.metrics = {};
|
||||
@ -141,6 +139,4 @@ Profiler.metric = function(name) {
|
||||
return new Metric(name);
|
||||
};
|
||||
|
||||
exports.Profiler = Profiler;
|
||||
|
||||
})(typeof exports === "undefined" ? this : exports);
|
||||
module.exports = Profiler;
|
||||
|
6
lib/torque/provider/index.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
json: require('./json'),
|
||||
JsonArray: require('./jsonarray'),
|
||||
windshaft: require('./windshaft'),
|
||||
tileJSON: require('./tilejson')
|
||||
};
|
@ -1,7 +1,5 @@
|
||||
(function(exports) {
|
||||
|
||||
var torque = exports.torque = exports.torque || {};
|
||||
var providers = exports.torque.providers = exports.torque.providers || {};
|
||||
var torque = require('../');
|
||||
var Profiler = require('../profiler');
|
||||
|
||||
var Uint8Array = torque.types.Uint8Array;
|
||||
var Int32Array = torque.types.Int32Array;
|
||||
@ -474,7 +472,7 @@
|
||||
torque.net.jsonp(url, function (data) {
|
||||
var query = format("select * from ({sql}) __torque_wrap_sql limit 0", { sql: self.getSQL() });
|
||||
self.sql(query, function (queryData) {
|
||||
if (data) {
|
||||
if (data && queryData) {
|
||||
callback({
|
||||
updated_at: data.last_updated,
|
||||
fields: queryData.fields
|
||||
@ -576,7 +574,4 @@
|
||||
|
||||
};
|
||||
|
||||
torque.providers.json = json;
|
||||
|
||||
|
||||
})(typeof exports === "undefined" ? this : exports);
|
||||
module.exports = json;
|