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 })
   ...