Jody from Tap Twice Tea's destinations on his current trip across Asia. Map made with d3. Thanks Mike Bostock for the great Let's Make a Map tutorial.
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <style> | |
| .country { | |
| fill: #B8B8B8; | |
| } | |
| .interior-boundary { | |
| fill: none; | |
| stroke: #FFFFFF; | |
| stroke-dasharray: 2,2; | |
| stroke-linejoin: round; | |
| } | |
| .place, | |
| .place-label { | |
| fill: #444; | |
| } | |
| text { | |
| font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
| font-size: 10px; | |
| pointer-events: none; | |
| } | |
| </style> | |
| <body> | |
| <script src="http://d3js.org/d3.v3.js"></script> | |
| <script src="http://d3js.org/d3.geo.projection.v0.min.js"></script> | |
| <script src="http://d3js.org/topojson.v1.js"></script> | |
| <script> | |
| var width = 1000, | |
| height = 590; | |
| // draw svg | |
| var svg = d3.select("body").append("svg") | |
| .attr("width", width) | |
| .attr("height", height); | |
| // map projection | |
| var projection = d3.geo.patterson() | |
| .center([58,54]) | |
| .scale(520) | |
| .translate([0,0]) | |
| .precision(.1); | |
| // path generator | |
| var path = d3.geo.path() | |
| .projection(projection) | |
| .pointRadius(1.5); | |
| // coordinates are added when constructRoute is called | |
| var journey = [ | |
| {name:"Kolkata", dates:"Feb. 17 - 22"}, | |
| {name:"Darjeeling", dates:"Feb. 23 - 28"}, | |
| {name:"Nepal", dates:"March 1 - 6"}, | |
| {name:"Myanmar", dates:"March 7 - 10"}, | |
| {name:"Cambodia", dates:"March 11 - 13"}, | |
| {name:"Laos", dates:"March 14 - 18"}, | |
| {name:"Xishuangbanna", dates:"March 18 - 21"}, | |
| {name:"Anhui", dates:"March 22 - 28"}, | |
| {name:"Fujian", dates:"March 29 - 31"}, | |
| {name:"Wuyi", dates:"April 1 - 6"}, | |
| {name:"Qingdao", dates:"April 6 - 10"}, | |
| {name:"Lishan", dates:"April 11 - 14"}, | |
| {name:"Nantou", dates:"April 15 - 18"}, | |
| {name:"Alishan", dates:"April 18 - 20"}, | |
| {name:"Taiwan", dates:"April 21 - 26"}, | |
| {name:"Shizuoka", dates:"April 27 - May 1"}, | |
| {name:"Uji", dates:"May 2 - 4"}, | |
| {name:"Kyoto", dates:"May 4 - 8"} | |
| ]; | |
| d3.json("asia.json", function(error, asia) { | |
| var subunits = topojson.feature(asia, asia.objects.subunits), | |
| places = topojson.feature(asia, asia.objects.places), | |
| route = constructRoute(journey, places.features); | |
| // draw the map | |
| svg.selectAll(".subunit") | |
| .data(subunits.features) | |
| .enter() | |
| .append("path") | |
| .attr("class", function(d) { return "country"; }) | |
| .attr("d", path); | |
| // draw interior boundaries between countries | |
| svg.append("path") | |
| .datum(topojson.mesh(asia, asia.objects.subunits, function(a, b) { | |
| return a !== b; | |
| })) | |
| .attr("d", path) | |
| .attr("class", "interior-boundary"); | |
| // draw places on map | |
| svg.append("path") | |
| .datum(places) | |
| .attr("d", path) | |
| .attr("class", "place"); | |
| // set all place labels | |
| svg.selectAll(".place-label") | |
| .data(places.features) | |
| .enter() | |
| .append("text") | |
| .attr("class", function(d) { return "place-label " + d.properties.name; }) | |
| .attr("transform", function(d) { return "translate(" + projection(d.geometry.coordinates) + ")"; }) | |
| .attr("x", function(d) { return d.geometry.coordinates[0] > -1 ? 6 : -6; }) | |
| .attr("dy", ".35em") | |
| .style("text-anchor", function(d) { return d.geometry.coordinates[0] > -1 ? "start" : "end"; }) | |
| .text(function(d) { return d.properties.name; }); | |
| // adjust Kyoto and Nantou labels | |
| svg.select(".place-label.Kyoto") | |
| .attr("x", -30) | |
| .attr("dy", ".15em"); | |
| // probably a better way than these magic numbers... | |
| svg.select(".place-label.Nantou") | |
| .attr("x", -38) | |
| .attr("dy", ".15em"); | |
| }); | |
| function constructRoute(journey, places) { | |
| // forming route for the path generator | |
| var route = { | |
| type: "LineString", | |
| coordinates: [] | |
| }; | |
| // add coords to journey and route | |
| journey.forEach(function(d) { | |
| places.forEach(function(p) { | |
| if (d.name == p.properties.name) { | |
| d.coords = p.geometry.coordinates; | |
| } | |
| }) | |
| route.coordinates.push(d.coords); | |
| }); | |
| return route; | |
| } | |
| </script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment