Skip to content

Instantly share code, notes, and snippets.

@rveciana
Last active January 3, 2016 12:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rveciana/8464690 to your computer and use it in GitHub Desktop.
Save rveciana/8464690 to your computer and use it in GitHub Desktop.
Haiyan typhoon track
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.graticule {
fill: none;
stroke: #777;
stroke-opacity: .5;
stroke-width: .5px;
}
.land {
fill: #999;
}
.boundary {
fill: none;
stroke: #fff;
stroke-width: .5px;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="http://d3js.org/colorbrewer.v1.min.js"></script>
<script>
var width = 600,
height = 500;
var projection = d3.geo.mercator()
.scale(5*(width + 1) / 2 / Math.PI)
.translate([width / 2, height / 2])
.rotate([-125, -15, 0])
.precision(.1);
var path = d3.geo.path()
.projection(projection);
var graticule = d3.geo.graticule();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("path")
.datum(graticule)
.attr("class", "graticule")
.attr("d", path);
d3.json("track.json", function(error, track) {
d3.json("/mbostock/raw/4090846/world-50m.json", function(error, world) {
var color_scale = d3.scale.quantile().domain([1, 5]).range(colorbrewer.YlOrRd[5]);
var filter = svg.append("defs")
.append("filter")
.attr("id", "drop-shadow")
.attr("height", "130%");
filter.append("feGaussianBlur")
.attr("in", "SourceAlpha")
.attr("stdDeviation", 5)
.attr("result", "blur");
filter.append("feOffset")
.attr("in", "blur")
.attr("dx", 5)
.attr("dy", 5)
.attr("result", "offsetBlur");
var feMerge = filter.append("feMerge");
feMerge.append("feMergeNode")
.attr("in", "offsetBlur")
feMerge.append("feMergeNode")
.attr("in", "SourceGraphic");
svg.insert("path", ".graticule")
.datum(topojson.feature(world, world.objects.land))
.attr("class", "land")
.attr("d", path)
.style("filter", "url(#drop-shadow)");
svg.insert("path", ".graticule")
.datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }))
.attr("class", "boundary")
.attr("d", path);
var dateText = svg.append("text")
.attr("id", "dataTitle")
.text("2013/11/"+track[0].day + " " + track[0].hour + ":00 class: " + track[0].class)
.attr("x", 70)
.attr("y", 20)
.attr("font-family", "sans-serif")
.attr("font-size", "20px")
.attr("fill", color_scale(track[0].class));
var pathLine = d3.svg.line()
.interpolate("cardinal")
.x(function(d) { return projection([d.lon, d.lat])[0]; })
.y(function(d) { return projection([d.lon, d.lat])[1]; });
var haiyanPath = svg.append("path")
.attr("d",pathLine(track))
.attr("fill","none")
.attr("stroke", color_scale(track[0].class))
.attr("stroke-width", 3)
.style('stroke-dasharray', function(d) {
var l = d3.select(this).node().getTotalLength();
return l + 'px, ' + l + 'px';
})
.style('stroke-dashoffset', function(d) {
return d3.select(this).node().getTotalLength() + 'px';
});
var haiyanPathEl = haiyanPath.node();
var haiyanPathElLen = haiyanPathEl.getTotalLength();
var pt = haiyanPathEl.getPointAtLength(0);
var icon = svg.append("path")
.attr("d","m 20,-42 c -21.61358,0.19629 -34.308391,10.76213 -41.46346,18.0657 -7.155097,7.3036 -11.451337,17.59059 -11.599112,26.13277 0,14.45439 9.037059,26.79801 21.767213,31.69368 -14.965519,10.64929 -25.578236,6.78076 -37.671451,7.85549 C -4.429787,54.20699 14.03,37.263 23.12144,28.41572 32.2133,19.56854 34.6802,10.79063 34.82941,2.19847 c 0,-14.45219 -9.03405,-26.79679 -21.76113,-31.69364 14.90401,-10.54656 25.48889,-6.69889 37.55061,-7.77104 C 38.78869,-40.57565 29.11666,-41.95733 21.03853,-42 20.68954,-42.0105 20.34303,-42.0105 20,-42 z M 0.82306,-7.46851 c 4.72694,0 8.56186,4.27392 8.56186,9.54602 0,5.2725 -3.83492,9.54651 -8.56186,9.54651 -4.726719,0 -8.555958,-4.27401 -8.555958,-9.54651 0,-5.2721 3.829239,-9.54602 8.555958,-9.54602 z")
.attr("transform", "translate(" + pt.x + "," + pt.y + "), scale("+(0.15*track[0].class)+")")
.attr("fill", color_scale(track[0].class))
.attr("class","icon");
var i = 0;
var animation = setInterval(function(){
pt = haiyanPathEl.getPointAtLength(haiyanPathElLen*i/track.length);
icon
.transition()
.ease("linear")
.duration(1000)
.attr("transform", "translate(" + pt.x + "," + pt.y + "), scale("+(0.15*track[i].class)+"), rotate("+(i*15)+")")
.attr("fill", color_scale(track[i].class));
haiyanPath
.transition()
.duration(1000)
.ease("linear")
.attr("stroke", color_scale(track[i].class))
.style('stroke-dashoffset', function(d) {
var stroke_offset = (haiyanPathElLen - haiyanPathElLen*i/track.length + 9);
return (haiyanPathElLen < stroke_offset) ? haiyanPathElLen : stroke_offset + 'px';
});
dateText
.text("2013/11/"+track[i].day + " " + track[i].hour + ":00 class: " + track[i].class)
.attr("fill", color_scale(track[i].class));
i = i + 1;
if (i==track.length)
clearInterval(animation)
},1000);
});
});
d3.select(self.frameElement).style("height", height + "px");
</script>
[{"day":3, "hour":18, "lat":6.1, "lon":153.3, "class": 2},{"day":3, "hour":21, "lat":6.1, "lon":152.8, "class": 2},{"day":4, "hour":0, "lat":6.1, "lon":152.2, "class": 3},{"day":4, "hour":3, "lat":6.2, "lon":151.2, "class": 3},{"day":4, "hour":6, "lat":6.2, "lon":150.4, "class": 3},{"day":4, "hour":9, "lat":6.2, "lon":149.5, "class": 3},{"day":4, "hour":12, "lat":6.3, "lon":148.6, "class": 3},{"day":4, "hour":15, "lat":6.3, "lon":148.4, "class": 3},{"day":4, "hour":18, "lat":6.5, "lon":147.6, "class": 3},{"day":4, "hour":21, "lat":6.5, "lon":147.0, "class": 3},{"day":5, "hour":0, "lat":6.5, "lon":145.9, "class": 4},{"day":5, "hour":3, "lat":6.5, "lon":145.2, "class": 4},{"day":5, "hour":6, "lat":6.5, "lon":144.6, "class": 4},{"day":5, "hour":9, "lat":6.5, "lon":144.0, "class": 4},{"day":5, "hour":12, "lat":6.9, "lon":143.1, "class": 4},{"day":5, "hour":15, "lat":7.0, "lon":142.1, "class": 4},{"day":5, "hour":18, "lat":7.1, "lon":141.3, "class": 5},{"day":5, "hour":21, "lat":7.3, "lon":140.5, "class": 5},{"day":6, "hour":0, "lat":7.3, "lon":139.7, "class": 5},{"day":6, "hour":3, "lat":7.5, "lon":138.9, "class": 5},{"day":6, "hour":6, "lat":7.6, "lon":138.0, "class": 5},{"day":6, "hour":9, "lat":7.7, "lon":137.2, "class": 5},{"day":6, "hour":12, "lat":7.9, "lon":136.2, "class": 5},{"day":6, "hour":15, "lat":8.1, "lon":135.3, "class": 5},{"day":6, "hour":18, "lat":8.2, "lon":134.4, "class": 5},{"day":6, "hour":21, "lat":8.4, "lon":133.6, "class": 5},{"day":7, "hour":0, "lat":8.7, "lon":132.8, "class": 5},{"day":7, "hour":3, "lat":9.0, "lon":131.9, "class": 5},{"day":7, "hour":6, "lat":9.3, "lon":131.1, "class": 5},{"day":7, "hour":9, "lat":9.8, "lon":130.2, "class": 5},{"day":7, "hour":12, "lat":10.2, "lon":129.1, "class": 5},{"day":7, "hour":15, "lat":10.4, "lon":128.0, "class": 5},{"day":7, "hour":18, "lat":10.6, "lon":126.9, "class": 5},{"day":7, "hour":21, "lat":10.8, "lon":125.9, "class": 5},{"day":8, "hour":0, "lat":11.0, "lon":124.8, "class": 5},{"day":8, "hour":3, "lat":11.2, "lon":123.7, "class": 5},{"day":8, "hour":6, "lat":11.4, "lon":122.6, "class": 5},{"day":8, "hour":9, "lat":11.5, "lon":121.6, "class": 5},{"day":8, "hour":12, "lat":11.8, "lon":120.7, "class": 5},{"day":8, "hour":15, "lat":12.3, "lon":119.4, "class": 5},{"day":8, "hour":18, "lat":12.4, "lon":118.2, "class": 5},{"day":8, "hour":21, "lat":12.5, "lon":117.3, "class": 5},{"day":9, "hour":0, "lat":12.3, "lon":116.6, "class": 5},{"day":9, "hour":3, "lat":12.9, "lon":115.6, "class": 5},{"day":9, "hour":9, "lat":13.9, "lon":113.9, "class": 5},{"day":9, "hour":12, "lat":14.4, "lon":113.1, "class": 5},{"day":9, "hour":15, "lat":15.0, "lon":112.2, "class": 5},{"day":9, "hour":18, "lat":15.4, "lon":111.4, "class": 5},{"day":9, "hour":21, "lat":15.9, "lon":111.1, "class": 5},{"day":10, "hour":0, "lat":16.5, "lon":110.3, "class": 5},{"day":10, "hour":3, "lat":17.0, "lon":109.7, "class": 5},{"day":10, "hour":6, "lat":17.8, "lon":109.0, "class": 5},{"day":10, "hour":9, "lat":18.5, "lon":108.4, "class": 5},{"day":10, "hour":12, "lat":19.4, "lon":108.1, "class": 5},{"day":10, "hour":15, "lat":19.8, "lon":107.9, "class": 5},{"day":10, "hour":18, "lat":20.3, "lon":107.5, "class": 4},{"day":10, "hour":21, "lat":20.8, "lon":107.1, "class": 4},{"day":11, "hour":0, "lat":21.3, "lon":107.2, "class": 4},{"day":11, "hour":3, "lat":22.0, "lon":107.2, "class": 4},{"day":11, "hour":6, "lat":22.3, "lon":107.4, "class": 3},{"day":11, "hour":9, "lat":22.6, "lon":107.6, "class": 3},{"day":11, "hour":12, "lat":23.0, "lon":107.0, "class": 2}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment