JSFiddle - React, Tailwind, and code Playground
by Gregor Aisch
HTML
<script src="https://rawgit.com/gka/d3-jetpack/master/build/d3v4+jetpack.js"></script>
JavaScript
console.clear()
d3.loadData('https://vis4.net/data/hurdat2.csv', function(err, res) {
data = res[0]
data.forEach((d, i) => {
if (d.Longitude.includes('E')){
d.Longitude = -d.Longitude.replace('E', '') + ''
}
if (d.Latitude.includes('S')){
d.Latitude = -d.Latitude.replace('S', '') + ''
}
d.i = i
})
byStorm = d3.nestBy(data, d => d.Serial)
byStorm.forEach(storm => {
storm.forEach((d, i) => {
d.maxWind = +d['Max wind']
d.day = i/4 // assumes data points a day
d.prev = i ? storm[i - 1] : null;
})
storm.maxWind = d3.max(storm, d => d.maxWind)
storm.forEach(d => {
d.color = storm.maxWind > 136 ? 1 : .1
})
// https://en.wikipedia.org/wiki/Accumulated_cyclone_energy
var ace = 0
storm.forEach(d => {
ace += d.maxWind*d.maxWind/10000
d.ace = ace
})
storm.ace = ace
})
byStorm = _.sortBy(byStorm, d => d.maxWind)
// calc positions for each step
var projection = d3
.geoConicConformal()
.parallels([18 + 2 / 60, 18 + 26 / 60])
.rotate([60 + 26 / 60, 13 - 50 / 60])
.fitSize([innerWidth, innerHeight], {
'type': 'LineString', 'coordinates': [[-95.2, 0.5], [-60.1, 16.5]]
})
var x = d3.scaleLinear().domain([0, 16]).range([0, innerWidth])
var windSpeedY = d3.scaleLinear().domain([40, 190]).range([innerHeight-20, 10])
var aceScaleY = d3.scaleLinear().domain([0, 90]).range([innerHeight-20, 10])
data.forEach(d => {
// position
d.pos0 = projection([-d.Longitude.replace('W', ''), d.Latitude.replace('N', '')])
// lon v. wind speed
d.pos1 = [d.pos0[0], windSpeedY(d.maxWind)]
// day v. wind speed
d.pos2 = [x(d.day), windSpeedY(d.maxWind)]
// day v. ACE
d.pos3 = [x(d.day), aceScaleY(d.ace)]
d.pos = [d.pos0, d.pos1, d.pos2, d.pos3];
});
var ctx = d3.select('body')
.st({overflow:'hidden'})
.append('canvas')
.at({ width: innerWidth, height: innerHeight })
...