Open in a new window for bigger view. This is improved version of Zoom to Group of Countries II with weekly data granularity.
Last active
October 18, 2015 18:32
-
-
Save darosh/0444bdd92c1f968c75ef to your computer and use it in GitHub Desktop.
Zoom to Group of Countries III
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ | |
[ | |
1010016000000, | |
{ | |
"IND": 6, | |
"USA": 1, | |
"PAK": 1, | |
"ISR": 1 | |
} | |
], | |
[ | |
1010620800000, | |
{ | |
"IND": 4, | |
"ISR": 4, | |
"IDN": 1, | |
"PAK": 1 | |
} | |
], | |
[ | |
1011225600000, | |
{ | |
"IND": 4, | |
"ISR": 1, | |
"BGD": 1 | |
} | |
], | |
[ | |
1011830400000, | |
{ | |
"IND": 6, | |
"ISR": 1 | |
} | |
], | |
[ | |
1012435200000, | |
{ | |
"IND": 5, | |
"DZA": 2, | |
"BGD": 1, | |
"PAK": 1, | |
"ISR": 1 | |
} | |
], | |
[ | |
1013040000000, | |
{ | |
"ISR": 3, | |
"IND": 3, | |
"DZA": 1, | |
"PAK": 1 | |
} | |
], | |
[ | |
1013644800000, | |
{ | |
"IND": 4, | |
"ISR": 3, | |
"DZA": 1 | |
} | |
], | |
[ | |
1014249600000, | |
{ | |
"IND": 6, | |
"ISR": 4, | |
"PAK": 3, | |
"NGA": 2, | |
"MAR": 1 | |
} | |
], | |
[ | |
1014854400000, | |
{ | |
"ISR": 9, | |
"IND": 4, | |
"PAK": 2, | |
"NGA": 1 | |
} | |
], | |
[ | |
1015459200000, | |
{ | |
"PAK": 5, | |
"ISR": 5, | |
"IND": 4, | |
"DZA": 1 | |
} | |
], | |
[ | |
1016064000000, | |
{ | |
"PAK": 5, | |
"ISR": 3, | |
"DZA": 3, | |
"IND": 3, | |
"USA": 1 | |
} | |
], | |
[ | |
1016668800000, | |
{ | |
"IND": 4, | |
"ISR": 3 | |
} | |
], | |
[ | |
1017273600000, | |
{ | |
"IND": 9, | |
"ISR": 4, | |
"PAK": 2, | |
"IDN": 1 | |
} | |
], | |
[ | |
1017878400000, | |
{ | |
"ISR": 3, | |
"IND": 3, | |
"AFG": 1, | |
"TUN": 1 | |
} | |
], | |
[ | |
1018483200000, | |
{ | |
"IND": 7, | |
"ISR": 1 | |
} | |
], | |
[ | |
1019088000000, | |
{ | |
"IND": 7, | |
"PAK": 2, | |
"DZA": 2, | |
"BGD": 1 | |
} | |
], | |
[ | |
1019692800000, | |
{ | |
"PAK": 3, | |
"IND": 2, | |
"DZA": 2, | |
"ISR": 1, | |
"SDN": 1, | |
"IDN": 1, | |
"BGD": 1 | |
} | |
], | |
[ | |
1020297600000, | |
{ | |
"PAK": 7, | |
"IND": 5, | |
"ISR": 1, | |
"RUS": 1 | |
} | |
], | |
[ | |
1020902400000, | |
{ | |
"IND": 5, | |
"DZA": 2, | |
"IDN": 1 | |
} | |
], | |
[ | |
1021507200000, | |
{ | |
"IND": 5, | |
"ISR": 2, | |
"PAK": 2 | |
} | |
], | |
[ | |
1022112000000, | |
{ | |
"IND": 6, | |
"ISR": 2, | |
"IDN": 1, | |
"USA": 1, | |
"PAK": 1 | |
} | |
], | |
[ | |
1022716800000, | |
{ | |
"IND": 7, | |
"GBR": 1, | |
"PHL": 1, | |
"IDN": 1, | |
"ISR": 1, | |
"AFG": 1, | |
"NGA": 1 | |
} | |
], | |
[ | |
1023321600000, | |
{ | |
"IND": 8, | |
"PAK": 2, | |
"IDN": 1, | |
"AFG": 1, | |
"DZA": 1 | |
} | |
], | |
[ | |
1023926400000, | |
{ | |
"IND": 4, | |
"PAK": 3, | |
"ISR": 3 | |
} | |
], | |
[ | |
1024531200000, | |
{ | |
"IND": 4, | |
"PAK": 2, | |
"DZA": 1 | |
} | |
], | |
[ | |
1025136000000, | |
{ | |
"IND": 6, | |
"DZA": 1, | |
"IDN": 1, | |
"PAK": 1, | |
"USA": 1 | |
} | |
], | |
[ | |
1025740800000, | |
{ | |
"IND": 7, | |
"DZA": 2, | |
"PHL": 1, | |
"IDN": 1 | |
} | |
], | |
[ | |
1026345600000, | |
{ | |
"IND": 8, | |
"DZA": 2, | |
"ISR": 2, | |
"IDN": 1, | |
"PAK": 1 | |
} | |
], | |
[ | |
1026950400000, | |
{ | |
"IND": 7, | |
"IDN": 2 | |
} | |
], | |
[ | |
1027555200000, | |
{ | |
"IND": 11, | |
"ISR": 3 | |
} | |
], | |
[ | |
1028160000000, | |
{ | |
"IND": 10, | |
"ISR": 2, | |
"IDN": 2, | |
"PAK": 1, | |
"DZA": 1 | |
} | |
], | |
[ | |
1028764800000, | |
{ | |
"IDN": 3, | |
"IND": 2, | |
"PAK": 1, | |
"PHL": 1, | |
"IRQ": 1, | |
"DZA": 1 | |
} | |
], | |
[ | |
1029369600000, | |
{ | |
"IND": 6, | |
"PAK": 1 | |
} | |
], | |
[ | |
1029974400000, | |
{ | |
"IND": 6 | |
} | |
], | |
[ | |
1030579200000, | |
{ | |
"IND": 6, | |
"AFG": 2, | |
"IDN": 1, | |
"DZA": 1, | |
"PAK": 1 | |
} | |
], | |
[ | |
1031184000000, | |
{ | |
"IND": 9, | |
"AFG": 1, | |
"IDN": 1 | |
} | |
], | |
[ | |
1031788800000, | |
{ | |
"IND": 7, | |
"PAK": 2, | |
"ISR": 1 | |
} | |
], | |
[ | |
1032393600000, | |
{ | |
"IND": 9, | |
"USA": 2, | |
"IDN": 1, | |
"PAK": 1 | |
} | |
], | |
[ | |
1032998400000, | |
{ | |
"IND": 9, | |
"USA": 2, | |
"BGD": 1, | |
"SAU": 1, | |
"PHL": 1, | |
"DZA": 1 | |
} | |
], | |
[ | |
1033603200000, | |
{ | |
"IND": 5, | |
"ISR": 2, | |
"YEM": 1, | |
"KWT": 1, | |
"USA": 1, | |
"PHL": 1 | |
} | |
], | |
[ | |
1034208000000, | |
{ | |
"IND": 3, | |
"USA": 2, | |
"DZA": 2, | |
"IDN": 1, | |
"PAK": 1, | |
"PHL": 1 | |
} | |
], | |
[ | |
1034812800000, | |
{ | |
"IND": 7, | |
"PHL": 2, | |
"PAK": 1, | |
"DZA": 1, | |
"ISR": 1, | |
"USA": 1, | |
"NGA": 1 | |
} | |
], | |
[ | |
1035417600000, | |
{ | |
"DZA": 2, | |
"IND": 2, | |
"ISR": 2, | |
"RUS": 1, | |
"JOR": 1, | |
"NGA": 1 | |
} | |
], | |
[ | |
1036022400000, | |
{ | |
"IND": 10, | |
"PAK": 2, | |
"ISR": 1, | |
"DZA": 1 | |
} | |
], | |
[ | |
1036627200000, | |
{ | |
"IND": 5, | |
"ISR": 1, | |
"DZA": 1 | |
} | |
], | |
[ | |
1037232000000, | |
{ | |
"IND": 5, | |
"ISR": 4, | |
"DZA": 3, | |
"PAK": 1, | |
"KWT": 1, | |
"LBN": 1 | |
} | |
], | |
[ | |
1037836800000, | |
{ | |
"IND": 7, | |
"NGA": 1, | |
"DZA": 1, | |
"ISR": 1, | |
"KEN": 1 | |
} | |
], | |
[ | |
1038441600000, | |
{ | |
"IND": 6, | |
"DZA": 1, | |
"PAK": 1, | |
"IDN": 1 | |
} | |
], | |
[ | |
1039046400000, | |
{ | |
"IND": 2, | |
"BGD": 1, | |
"PAK": 1, | |
"DZA": 1, | |
"NGA": 1, | |
"ISR": 1 | |
} | |
], | |
[ | |
1039651200000, | |
{ | |
"DZA": 3, | |
"IND": 2, | |
"RUS": 1, | |
"PAK": 1 | |
} | |
], | |
[ | |
1040256000000, | |
{ | |
"IND": 8, | |
"PAK": 2, | |
"PHL": 2 | |
} | |
], | |
[ | |
1040860800000, | |
{ | |
"IND": 5, | |
"ISR": 3, | |
"RUS": 1, | |
"DZA": 1, | |
"YEM": 1, | |
"PHL": 1 | |
} | |
], | |
[ | |
1041465600000, | |
{ | |
"DZA": 4, | |
"IND": 3, | |
"ISR": 1 | |
} | |
], | |
[ | |
1042070400000, | |
{ | |
"IND": 6, | |
"GBR": 2, | |
"ISR": 2, | |
"RUS": 1, | |
"PHL": 1 | |
} | |
], | |
[ | |
1042675200000, | |
{ | |
"IND": 8, | |
"ISR": 3, | |
"BGD": 2, | |
"KWT": 1, | |
"PAK": 1 | |
} | |
], | |
[ | |
1043280000000, | |
{ | |
"IND": 4, | |
"LBN": 1, | |
"AFG": 1, | |
"PSX": 1, | |
"ISR": 1 | |
} | |
], | |
[ | |
1043884800000, | |
{ | |
"PAK": 4, | |
"IND": 4, | |
"RUS": 2, | |
"AFG": 1, | |
"DZA": 1, | |
"ISR": 1 | |
} | |
], | |
[ | |
1044489600000, | |
{ | |
"IND": 5, | |
"IRQ": 1, | |
"DZA": 1, | |
"RUS": 1, | |
"AFG": 1, | |
"PHL": 1, | |
"ISR": 1 | |
} | |
], | |
[ | |
1045094400000, | |
{ | |
"PHL": 4, | |
"IND": 2, | |
"SAU": 2, | |
"ISR": 1, | |
"DZA": 1 | |
} | |
], | |
[ | |
1045699200000, | |
{ | |
"IND": 5, | |
"PAK": 5, | |
"DZA": 3, | |
"PHL": 1, | |
"AFG": 1, | |
"TLS": 1, | |
"IRQ": 1, | |
"RUS": 1 | |
} | |
], | |
[ | |
1046304000000, | |
{ | |
"PHL": 3, | |
"IND": 2, | |
"PAK": 1, | |
"LBN": 1, | |
"BGD": 1, | |
"RUS": 1, | |
"ISR": 1 | |
} | |
], | |
[ | |
1046908800000, | |
{ | |
"IND": 6, | |
"PHL": 2, | |
"ISR": 2, | |
"BGD": 1, | |
"AFG": 1 | |
} | |
], | |
[ | |
1047513600000, | |
{ | |
"IND": 8, | |
"PHL": 4, | |
"NGA": 1, | |
"AFG": 1, | |
"LBN": 1 | |
} | |
], | |
[ | |
1048118400000, | |
{ | |
"IND": 9, | |
"DZA": 3, | |
"PHL": 2, | |
"RUS": 2, | |
"IRQ": 1, | |
"KWT": 1, | |
"AFG": 1 | |
} | |
], | |
[ | |
1048723200000, | |
{ | |
"IND": 6, | |
"PHL": 4, | |
"DZA": 1, | |
"IRQ": 1, | |
"ISR": 1, | |
"IRN": 1, | |
"AFG": 1 | |
} | |
], | |
[ | |
1049328000000, | |
{ | |
"IRQ": 4, | |
"IND": 4, | |
"PHL": 3, | |
"RUS": 2, | |
"IDN": 1, | |
"PAK": 1, | |
"NGA": 1, | |
"AFG": 1, | |
"ISR": 1 | |
} | |
], | |
[ | |
1049932800000, | |
{ | |
"IND": 6, | |
"AFG": 4, | |
"RUS": 2, | |
"PHL": 2, | |
"ISR": 1 | |
} | |
], | |
[ | |
1050537600000, | |
{ | |
"IND": 5, | |
"PHL": 2, | |
"LKA": 1, | |
"ERI": 1, | |
"NGA": 1, | |
"AFG": 1, | |
"RUS": 1, | |
"ISR": 1 | |
} | |
], | |
[ | |
1051142400000, | |
{ | |
"IND": 8, | |
"IDN": 1, | |
"AFG": 1, | |
"ISR": 1, | |
"PHL": 1, | |
"SDN": 1 | |
} | |
], | |
[ | |
1051747200000, | |
{ | |
"IND": 4, | |
"PHL": 2, | |
"DZA": 2, | |
"ISR": 1, | |
"RUS": 1, | |
"AFG": 1, | |
"LBN": 1 | |
} | |
], | |
[ | |
1052352000000, | |
{ | |
"IND": 9, | |
"RUS": 3, | |
"PAK": 2, | |
"PHL": 1, | |
"ISR": 1, | |
"SAU": 1, | |
"YEM": 1 | |
} | |
], | |
[ | |
1052956800000, | |
{ | |
"IND": 11, | |
"ISR": 3, | |
"MAR": 1, | |
"DZA": 1, | |
"PAK": 1, | |
"SDN": 1 | |
} | |
], | |
[ | |
1053561600000, | |
{ | |
"IND": 5, | |
"DZA": 2, | |
"PAK": 1, | |
"ISR": 1, | |
"RUS": 1, | |
"IDN": 1, | |
"PHL": 1 | |
} | |
], | |
[ | |
1054166400000, | |
{ | |
"IND": 7, | |
"RUS": 2, | |
"DZA": 2, | |
"SAU": 1, | |
"PAK": 1, | |
"IDN": 1, | |
"KOS": 1, | |
"AFG": 1 | |
} | |
], | |
[ | |
1054771200000, | |
{ | |
"IND": 9, | |
"PAK": 2, | |
"ISR": 2, | |
"AFG": 2, | |
"DZA": 2, | |
"TUR": 1, | |
"NGA": 1, | |
"RUS": 1 | |
} | |
], | |
[ | |
1055376000000, | |
{ | |
"IND": 4, | |
"DZA": 3, | |
"ISR": 2, | |
"RUS": 1, | |
"IRQ": 1 | |
} | |
], | |
[ | |
1055980800000, | |
{ | |
"IND": 8, | |
"DZA": 3, | |
"ISR": 3, | |
"IRQ": 2, | |
"PAK": 1, | |
"RUS": 1, | |
"AFG": 1 | |
} | |
], | |
[ | |
1056585600000, | |
{ | |
"IND": 9, | |
"IRQ": 2, | |
"DZA": 1, | |
"RUS": 1, | |
"ISR": 1 | |
} | |
], | |
[ | |
1057190400000, | |
{ | |
"IND": 7, | |
"IRQ": 3, | |
"PAK": 2, | |
"RUS": 3, | |
"ISR": 2, | |
"IDN": 2, | |
"DZA": 1, | |
"IRN": 1, | |
"PHL": 1 | |
} | |
], | |
[ | |
1057795200000, | |
{ | |
"IND": 9, | |
"RUS": 5, | |
"PAK": 2, | |
"DZA": 2, | |
"AFG": 1, | |
"ISR": 1, | |
"IRQ": 1 | |
} | |
], | |
[ | |
1058400000000, | |
{ | |
"IND": 5, | |
"IRQ": 3, | |
"AFG": 1, | |
"RUS": 1 | |
} | |
], | |
[ | |
1059004800000, | |
{ | |
"IND": 9, | |
"AFG": 4, | |
"RUS": 3, | |
"PAK": 2, | |
"DZA": 2, | |
"KOS": 1, | |
"SDN": 1, | |
"IRQ": 1, | |
"PSX": 1, | |
"PHL": 1 | |
} | |
], | |
[ | |
1059609600000, | |
{ | |
"IND": 6, | |
"IRQ": 3, | |
"RUS": 2, | |
"DZA": 1, | |
"ISR": 1, | |
"IDN": 1, | |
"USA": 1, | |
"AFG": 1 | |
} | |
], | |
[ | |
1060214400000, | |
{ | |
"IND": 9, | |
"ISR": 3, | |
"AFG": 3, | |
"PAK": 2, | |
"RUS": 2, | |
"KOS": 1, | |
"SAU": 1, | |
"IRQ": 1 | |
} | |
], | |
[ | |
1060819200000, | |
{ | |
"IND": 6, | |
"IRQ": 3, | |
"PAK": 2, | |
"AFG": 2, | |
"ISR": 1, | |
"RUS": 1 | |
} | |
], | |
[ | |
1061424000000, | |
{ | |
"IND": 5, | |
"IRQ": 2, | |
"AFG": 2, | |
"PHL": 1, | |
"PAK": 1, | |
"RUS": 3 | |
} | |
], | |
[ | |
1062028800000, | |
{ | |
"IND": 9, | |
"IRQ": 4, | |
"ISR": 2, | |
"PAK": 2, | |
"SDN": 1, | |
"KOS": 1, | |
"RUS": 1 | |
} | |
], | |
[ | |
1062633600000, | |
{ | |
"IND": 6, | |
"AFG": 3, | |
"IRQ": 3, | |
"ISR": 2, | |
"DZA": 1, | |
"GBR": 1 | |
} | |
], | |
[ | |
1063238400000, | |
{ | |
"IND": 8, | |
"IRQ": 2, | |
"RUS": 1, | |
"PHL": 1, | |
"DZA": 1, | |
"AFG": 1 | |
} | |
], | |
[ | |
1063843200000, | |
{ | |
"IRQ": 6, | |
"IND": 4, | |
"DZA": 1, | |
"ISR": 1, | |
"AFG": 1 | |
} | |
], | |
[ | |
1064448000000, | |
{ | |
"IND": 6, | |
"IRQ": 2, | |
"KOS": 1, | |
"PAK": 1, | |
"AFG": 1, | |
"BGD": 1, | |
"ISR": 1, | |
"DZA": 1, | |
"RUS": 2, | |
"IDN": 1, | |
"SOM": 1 | |
} | |
], | |
[ | |
1065052800000, | |
{ | |
"IRQ": 7, | |
"IND": 4, | |
"PAK": 3, | |
"ISR": 3, | |
"AFG": 2, | |
"PHL": 2, | |
"DZA": 2, | |
"SOM": 1, | |
"LBN": 1, | |
"IDN": 1 | |
} | |
], | |
[ | |
1065657600000, | |
{ | |
"IRQ": 6, | |
"IND": 4, | |
"RUS": 2, | |
"IDN": 1, | |
"AFG": 1, | |
"DZA": 1, | |
"ISR": 1 | |
} | |
], | |
[ | |
1066262400000, | |
{ | |
"IND": 3, | |
"AFG": 2, | |
"ISR": 2, | |
"RUS": 1, | |
"SOM": 1 | |
} | |
], | |
[ | |
1066867200000, | |
{ | |
"IRQ": 10, | |
"IND": 8, | |
"PHL": 2, | |
"DZA": 2, | |
"ISR": 1, | |
"AFG": 1, | |
"THA": 1, | |
"IDN": 1 | |
} | |
], | |
[ | |
1067472000000, | |
{ | |
"IND": 6, | |
"IRQ": 4, | |
"BGD": 1, | |
"ISR": 1, | |
"SAU": 1 | |
} | |
], | |
[ | |
1068076800000, | |
{ | |
"IRQ": 4, | |
"IND": 3, | |
"SDN": 1, | |
"DZA": 1, | |
"SAU": 1, | |
"PHL": 1, | |
"AFG": 1 | |
} | |
], | |
[ | |
1068681600000, | |
{ | |
"IND": 5, | |
"IRQ": 2, | |
"TUR": 2, | |
"IDN": 2, | |
"AFG": 2, | |
"RUS": 1, | |
"DZA": 1, | |
"JOR": 1, | |
"BGD": 1, | |
"FRA": 1, | |
"ISR": 1 | |
} | |
], | |
[ | |
1069286400000, | |
{ | |
"IND": 4, | |
"IRQ": 4, | |
"ISR": 2, | |
"PHL": 1 | |
} | |
], | |
[ | |
1069891200000, | |
{ | |
"IND": 4, | |
"IRQ": 3, | |
"DZA": 1, | |
"IDN": 1, | |
"USA": 1, | |
"PHL": 1, | |
"AFG": 1, | |
"YEM": 1 | |
} | |
] | |
] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
* { | |
line-height: 20px; | |
font-family: Calibri, Arial, Helvetica, sans-serif; | |
color: #999; | |
margin: 0; | |
padding: 0; | |
text-align: center; | |
text-rendering: optimizelegibility; | |
} | |
canvas { | |
display: block; | |
border-bottom: 1px solid #dedede; | |
} | |
svg { | |
position: absolute; | |
right: 0; | |
top: 0; | |
display: none; | |
} | |
.axis .domain { | |
display: none; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
stroke-opacity: 0.87; | |
stroke-width: 1; | |
} | |
.axis text { | |
font: 16px Calibri, Arial, Helvetica, sans-serif; | |
fill: #000; | |
fill-opacity: 0.87; | |
} | |
</style> | |
<body> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script> | |
<script src="utils.js"></script> | |
<script> | |
var width = 960; | |
var height = 480; | |
var canvasScale = ((document.body.clientWidth > width) ? document.body.clientWidth : width) / width; | |
width *= canvasScale; | |
height *= canvasScale; | |
var valueInterpolation = d3.interpolate('#f89f00', '#f80000'); | |
var maxScale = 3; | |
var scaleMargin = (40 * canvasScale / width); | |
var maxCountry = (48 * canvasScale / width); | |
var config = { | |
durationMin: 800, | |
durationMax: 1200, | |
interval: 1000, | |
fontSize: 16, | |
fontShift: 2, | |
font: 'Arial, Helvetica, sans-serif', | |
land: { | |
fillStyle: '#bbb', | |
shadowColor: '#000', | |
shadowOffsetY: 1, | |
shadowBlur: 1 | |
}, | |
border: { | |
lineWidth: 0.75, | |
strokeStyle: '#fff', | |
shadowColor: '#eee', | |
shadowOffsetY: -1 | |
}, | |
past: { | |
fillStyle: '#9c8f8f', | |
shadowColor: '#fff', | |
shadowOffsetY: -1, | |
shadowBlur: 0 | |
}, | |
names: { | |
shadowOffsetY: 2, | |
fillStyle: '#fff', | |
shadowColor: 'rgba(0,0,0,0.87)', | |
strokeStyle: '#888', | |
shadowBlur: 4, | |
lineWidth: 0 | |
}, | |
graticule: { | |
strokeStyle: '#aaa', | |
lineWidth: 0.25, | |
shadowOffsetY: 0, | |
shadowBlur: 0 | |
} | |
}; | |
var centroidsShifts = { | |
USA: [30, 10], | |
IRN: [0, 5], | |
FRA: [20, -20], | |
IND: [-2, 8], | |
MAR: [0, -6], | |
CAN: [-22, 7], | |
IRQ: [2, 2], | |
SYR: [0, -2] | |
}; | |
var rusUsaShift = 12; | |
var mini = 0.2; | |
var miniHeight = mini; | |
var canvas = d3.select('body').append('canvas').attr('width', width).attr('height', height); | |
var info = d3.select('body').append('div'); | |
var ctx = canvas.node().getContext('2d'); | |
var projection = d3.geo.equirectangular().translate([width / 2, height / 2]).scale(153 * canvasScale).rotate([-rusUsaShift, 0, 0]); | |
projection.precision(0); | |
var path = d3.geo.path().projection(projection).context(ctx); | |
var graticule = d3.geo.graticule().step([10, 10]).extent([[-180, -90.001], [180, 90.001]])(); | |
var miniProjection = d3.geo.equirectangular().clipExtent([[0, 0], [width * mini, height * miniHeight]]).translate([width * mini / 2, height * miniHeight / 2]).scale(153 * canvasScale * mini).rotate([-rusUsaShift, 0, 0]); | |
var miniPath = d3.geo.path().projection(miniProjection).context(ctx); | |
var currentScale = 1; | |
var currentTranslate = [0, 0]; | |
var pastCountries = {}; | |
var pastColors = {}; | |
var currentEventIndex = -1; | |
var loadedEvents; | |
var land, borders, countries = {}; | |
var scale = d3.scale.linear() | |
.domain([1, 2]) | |
.range([0, 380]); | |
var svg = d3.select('body').append('svg') | |
.attr('width', 400) | |
.attr('height', 35); | |
svg.append('svg:rect') | |
.attr('width', 400) | |
.attr('height', 36) | |
.style('fill-opacity', 0.4) | |
.style('fill', '#fff'); | |
var gradient = svg.append('svg:defs') | |
.append('svg:linearGradient') | |
.attr('id', 'gradient') | |
.attr('x1', '0%') | |
.attr('y1', '0%') | |
.attr('x2', '100%') | |
.attr('y2', '0%') | |
.attr('spreadMethod', 'pad'); | |
gradient.append('svg:stop') | |
.attr('offset', '0%') | |
.attr('stop-color', valueInterpolation(0)) | |
.attr('stop-opacity', 1); | |
gradient.append('svg:stop') | |
.attr('offset', '100%') | |
.attr('stop-color', valueInterpolation(1)) | |
.attr('stop-opacity', 1); | |
svg.append('svg:rect') | |
.attr('width', 380) | |
.attr('transform', 'translate(10,7)') | |
.attr('height', 8) | |
.style('stroke-width', 0) | |
.style('fill', 'url(#gradient)'); | |
var axis = d3.svg.axis() | |
.scale(scale) | |
.ticks(1) | |
.tickSize(8) | |
.orient("bottom"); | |
var legend = svg.append("g") | |
.attr("class", "axis axis--x") | |
.attr("transform", "translate(10,7)") | |
.call(axis); | |
d3.json('/darosh/raw/2d12a584a14910032ab8/countries.json', function (world) { | |
initWorld(world); | |
d3.json('events.json', function (events) { | |
loadedEvents = events; | |
update(); | |
}); | |
}); | |
function update() { | |
var e = loadedEvents[currentEventIndex]; | |
if (e) { | |
svg.style('display', 'block'); | |
var d = new Date(e[0]); | |
var mm = getValuesMinMax(e[1]); | |
info.text('Week: ' + (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear() + | |
', Record: ' + (currentEventIndex + 1) + ' of ' + loadedEvents.length + | |
', Countries: ' + Object.keys(e[1]).length + | |
', Past countries: ' + Object.keys(pastCountries).length + | |
', Min: ' + mm.min + ', Max: ' + mm.max + ', Sum: ' + mm.sum); | |
scale.domain(!(mm.max - mm.min) ? [mm.min - 0.5, mm.max + 0.5] : [mm.min, mm.max]); | |
axis.ticks((mm.max - mm.min) || 1); | |
legend.transition().duration(config.durationMin).call(axis); | |
transition(e[1]); | |
} else { | |
transition({}); | |
} | |
currentEventIndex++; | |
if (currentEventIndex < loadedEvents.length) { | |
setTimeout(update, config.interval); | |
} else { | |
setTimeout(function () { | |
config.durationMax *= 2; | |
info.text(''); | |
svg.style('display', 'none'); | |
transition({}); | |
}, config.interval); | |
} | |
} | |
function initWorld(world) { | |
land = topojson.merge(world, world.objects.countries.geometries); | |
borders = topojson.mesh(world, world.objects.countries, function (a, b) { | |
return a !== b; | |
}); | |
topojson.feature(world, world.objects.countries).features.forEach(function (v) { | |
countries[v.id] = v; | |
}); | |
} | |
function transition(values) { | |
var selectedFeatures = Object.keys(values).map(function (v) { | |
return countries[v]; | |
}); | |
var currentRotation = projection.rotate(); | |
var targetRotation = !values['RUS'] && values['USA'] ? [+rusUsaShift, 0] : [-rusUsaShift, 0]; | |
var rotationInterpolation = d3.interpolate(currentRotation, targetRotation, 'easeIn'); | |
projection.rotate(targetRotation); | |
var bound = groupBounds(path, selectedFeatures, width, height, maxCountry * width, maxCountry * height); | |
var size = [bound[1][0] - bound[0][0], bound[1][1] - bound[0][1]]; | |
var targetScale = getScale(size, width, height, scaleMargin, maxScale); | |
var targetCenter = [(bound[0][0] + bound[1][0]) / 2, (bound[0][1] + bound[1][1]) / 2]; | |
var realCenter = [width / 2, height / 2]; | |
var scaledBox = [ | |
[targetCenter[0] - realCenter[0] / targetScale, | |
targetCenter[1] - realCenter[1] / targetScale], | |
[targetCenter[0] + realCenter[0] / targetScale, | |
targetCenter[1] + realCenter[1] / targetScale]]; | |
scaledBox[0][1] = scaledBox[0][1] < 0 ? 0 : scaledBox[0][1]; | |
var targetTranslate = [-scaledBox[0][0] * targetScale, -scaledBox[0][1] * targetScale]; | |
var minMax = getValuesMinMax(values); | |
var zoomInterpolation = d3.interpolateZoom([currentTranslate[0], currentTranslate[1], width * currentScale], | |
[targetTranslate[0], targetTranslate[1], width * targetScale]); | |
d3.transition() | |
.duration(Math.min(config.durationMax, Math.max(config.durationMin, 2.5 * zoomInterpolation.duration))) | |
.tween('tween', function getTween() { | |
return function drawTween(t) { | |
// Clear | |
ctx.globalAlpha = 1; | |
ctx.setTransform(1, 0, 0, 1, 0, 0); | |
ctx.clearRect(0, 0, width, height); | |
// Transform | |
var zoom = zoomInterpolation(t); | |
projection.rotate(rotationInterpolation(t)); | |
currentTranslate = [zoom[0], zoom[1]]; | |
ctx.translate(currentTranslate[0], currentTranslate[1]); | |
currentScale = zoom[2] / width; | |
ctx.scale(currentScale, currentScale); | |
// Graticule | |
ctx.beginPath(); | |
setContextSyle(ctx, config.graticule); | |
ctx.lineWidth = config.graticule.lineWidth / currentScale; | |
path(graticule); | |
ctx.stroke(); | |
// Land | |
ctx.beginPath(); | |
setContextSyle(ctx, config.land); | |
path(land); | |
ctx.fill(); | |
// Past | |
ctx.beginPath(); | |
setContextSyle(ctx, config.past); | |
Object.keys(pastCountries).forEach(function fillPast(id) { | |
if (!values[id]) { | |
path(countries[id]); | |
pastColors[id] = config.past.fillStyle; | |
} | |
}); | |
ctx.fill(); | |
// Current | |
selectedFeatures.forEach(function fillNow(f) { | |
ctx.beginPath(); | |
ctx.fillStyle = d3.interpolate(pastColors[f.id] || config.land.fillStyle, valueInterpolation(normalize(values[f.id], minMax)), 'easeIn')(t); | |
pastColors[f.id] = ctx.fillStyle; | |
path(f); | |
ctx.fill(); | |
pastCountries[f.id] = true; | |
}); | |
// Borders | |
ctx.beginPath(); | |
setContextSyle(ctx, config.border); | |
ctx.lineWidth = config.border.lineWidth / currentScale; | |
path(borders); | |
ctx.stroke(); | |
// Names | |
setContextSyle(ctx, config.names); | |
ctx.font = config.fontSize * canvasScale / currentScale + 'px ' + config.font; | |
ctx.textAlign = 'center'; | |
selectedFeatures.forEach(function addCountryName(f) { | |
var x = path.centroid(f); | |
var name = (f.properties.name).split(',')[0]; | |
if (centroidsShifts[f.id]) { | |
x[0] += centroidsShifts[f.id][0] * canvasScale / currentScale; | |
x[1] += centroidsShifts[f.id][1] * canvasScale / currentScale; | |
} | |
ctx.shadowBlur = config.names.shadowBlur * canvasScale / currentScale; | |
ctx.lineWidth = config.names.lineWidth * canvasScale / currentScale; | |
ctx.shadowOffsetY = config.names.shadowOffsetY * canvasScale / currentScale; | |
ctx.fillText(name, x[0], x[1] + config.fontShift * canvasScale / currentScale); | |
}); | |
// Preview | |
miniProjection.rotate(targetRotation); | |
ctx.globalAlpha = 0.4; | |
ctx.setTransform(1, 0, 0, 1, 0, 0); | |
ctx.translate(0, height - height * miniHeight); | |
ctx.beginPath(); | |
ctx.shadowOffsetY = 0; | |
ctx.shadowColor = '#fff'; | |
ctx.shadowBlur = 0; | |
ctx.fillStyle = '#ccc'; | |
ctx.fillRect(0, 0, width * mini, height * miniHeight); | |
ctx.beginPath(); | |
setContextSyle(ctx, config.land); | |
ctx.fillStyle = '#666'; | |
ctx.shadowOffsetY = 0; | |
ctx.shadowBlur = 0; | |
miniPath(land); | |
ctx.fill(); | |
selectedFeatures.forEach(function fillNow(f) { | |
ctx.beginPath(); | |
ctx.fillStyle = valueInterpolation(1); | |
miniPath(f); | |
ctx.fill(); | |
pastCountries[f.id] = true; | |
}); | |
ctx.beginPath(); | |
ctx.globalAlpha = 0.4; | |
ctx.fillStyle = '#f20'; | |
ctx.scale(mini, mini); | |
var b = scaledBox; | |
ctx.fillRect(b[0][0], b[0][1], b[1][0] - b[0][0], b[1][1] - b[0][1]); | |
}; | |
}) | |
.transition(); | |
} | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function limitBounds(b, maxWidth, maxHeight) { | |
var w = b[1][0] - b[0][0]; | |
if (w > maxWidth) { | |
var c = (b[1][0] + b[0][0]) / 2; | |
maxWidth /= 2; | |
b[0][0] = c - maxWidth; | |
b[1][0] = c + maxWidth; | |
} | |
var h = b[1][1] - b[0][1]; | |
if (h > maxHeight) { | |
var ch = (b[1][1] + b[0][1]) / 2; | |
maxHeight /= 2; | |
b[0][1] = ch - maxHeight; | |
b[1][1] = ch + maxHeight; | |
} | |
} | |
function groupBounds(path, features, width, height, maxWidth, maxHeight) { | |
var r = features.length ? [[[], []], [[], []]] : [[[0], [0]], [[width], [height]]]; | |
features.forEach(function (feature) { | |
var b = path.bounds(feature); | |
limitBounds(b, maxWidth, maxHeight); | |
r[0][0].push(b[0][0]); | |
r[0][1].push(b[0][1]); | |
r[1][0].push(b[1][0]); | |
r[1][1].push(b[1][1]); | |
}); | |
r[0][0] = Math.min.apply(this, r[0][0]); | |
r[0][1] = Math.min.apply(this, r[0][1]); | |
r[1][0] = Math.max.apply(this, r[1][0]); | |
r[1][1] = Math.max.apply(this, r[1][1]); | |
return r; | |
} | |
function normalize(v, minMax) { | |
return minMax.diff ? (v - minMax.min) / minMax.diff : 0.5; | |
} | |
function getValuesMinMax(values) { | |
var v = []; | |
var s = 0; | |
for (var k in values) { | |
v.push(values[k]); | |
s += values[k]; | |
} | |
var r = { | |
min: Math.min.apply(this, v), | |
max: Math.max.apply(this, v) | |
}; | |
r.diff = r.max - r.min; | |
r.sum = s; | |
return r; | |
} | |
function getScale(size, width, height, scaleMargin, maxScale) { | |
var marginSize = [(size[0] + width * scaleMargin), (size[1] + width * scaleMargin)]; | |
var sizeRatio = marginSize[0] / marginSize[1]; | |
var boxRatio = width / height; | |
var r; | |
if (sizeRatio >= boxRatio) { | |
r = width / marginSize[0]; | |
} else { | |
r = height / marginSize[1]; | |
} | |
if (r < 1) { | |
r = 1; | |
} else if (r > maxScale) { | |
r = maxScale; | |
} | |
return r; | |
} | |
function setContextSyle(ctx, opt) { | |
ctx.fillStyle = opt.fillStyle; | |
ctx.strokeStyle = opt.strokeStyle; | |
ctx.shadowColor= opt.shadowColor; | |
ctx.shadowOffsetY = opt.shadowOffsetY; | |
ctx.shadowBlur = opt.shadowBlur; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment