Last active
March 16, 2020 15:03
-
-
Save bradoyler/12b0895665ffa6e6b79652e7c48769b8 to your computer and use it in GitHub Desktop.
Flu Illness Cartogram
This file contains 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
license: mit |
A Weekly Influenza Surveillance Report Prepared by the Influenza Division
Influenza-Like Illness (ILI) Activity Level Indicator Determined by Data Reported to ILINet
Data source: https://gis.cdc.gov/grasp/fluview/main.html
This Data visualization was created for the story Flu Frenzy - NBCNews.com
This file contains 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> | |
<head> | |
<meta charset="utf-8"> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.18.1/babel.min.js"></script> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/3.0.0/topojson.min.js"></script> | |
<style> | |
#cartogram { | |
max-width: 600px; | |
margin: auto; | |
} | |
.week-label { | |
font-family: Helvetica; | |
font-size: 1em; | |
color: #fff; | |
} | |
body { | |
background-color:#000; margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } | |
</style> | |
</head> | |
<body> | |
<div id="cartogram"></div> | |
<script type="text/babel" src="index.js"></script> | |
</body> |
This file contains 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
const statesJson = {"AL":{"name":"Alabama","pop_2014":4849377,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":2,"W41":2,"W42":2,"W43":3,"W44":4,"W45":4,"W46":5,"W47":5,"W48":5,"W49":7,"W50":10,"W51":10,"W52":10},"AK":{"name":"Alaska","pop_2014":736732,"W1":6,"W2":6,"W3":6,"W4":8,"W5":10,"W6":10,"W40":1,"W41":2,"W42":4,"W43":3,"W44":2,"W45":2,"W46":4,"W47":4,"W48":5,"W49":6,"W50":5,"W51":6,"W52":7},"AZ":{"name":"Arizona","pop_2014":6731484,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":2,"W41":2,"W42":1,"W43":2,"W44":3,"W45":3,"W46":3,"W47":3,"W48":3,"W49":6,"W50":10,"W51":10,"W52":10},"AR":{"name":"Arkansas","pop_2014":2966369,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":3,"W47":1,"W48":4,"W49":8,"W50":10,"W51":10,"W52":10},"CA":{"name":"California","pop_2014":38802500,"W1":10,"W2":10,"W3":8,"W4":8,"W5":9,"W6":8,"W40":2,"W41":1,"W42":1,"W43":1,"W44":2,"W45":2,"W46":2,"W47":3,"W48":2,"W49":4,"W50":7,"W51":10,"W52":10},"CO":{"name":"Colorado","pop_2014":5355866,"W1":8,"W2":7,"W3":7,"W4":8,"W5":10,"W6":9,"W40":1,"W41":1,"W42":1,"W43":1,"W44":2,"W45":2,"W46":2,"W47":3,"W48":3,"W49":4,"W50":5,"W51":6,"W52":7},"CT":{"name":"Connecticut","pop_2014":3596677,"W1":4,"W2":5,"W3":9,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":2,"W49":2,"W50":3,"W51":2,"W52":3},"DC":{"name":"District of Columbia","pop_2014":658893,"W1":5,"W2":5,"W3":7,"W4":10,"W5":10,"W6":10,"W40":2,"W41":2,"W42":2,"W43":2,"W44":2,"W45":3,"W46":3,"W47":3,"W48":4,"W49":4,"W50":4,"W51":3,"W52":5},"DE":{"name":"Delaware","pop_2014":935614,"W1":1,"W2":1,"W3":2,"W4":5,"W5":8,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":1,"W50":1,"W51":1,"W52":1},"FL":{"name":"Florida","pop_2014":19893297,"W1":5,"W2":9,"W3":10,"W4":10,"W5":10,"W6":9,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":2,"W46":2,"W47":1,"W48":1,"W49":1,"W50":2,"W51":4,"W52":5},"GA":{"name":"Georgia","pop_2014":10097343,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":2,"W41":3,"W42":3,"W43":4,"W44":4,"W45":5,"W46":6,"W47":7,"W48":6,"W49":7,"W50":7,"W51":10,"W52":10},"HI":{"name":"Hawaii","pop_2014":1419561,"W1":5,"W2":8,"W3":7,"W4":8,"W5":6,"W6":5,"W40":1,"W41":1,"W42":1,"W43":1,"W44":2,"W45":3,"W46":3,"W47":3,"W48":5,"W49":5,"W50":3,"W51":6,"W52":7},"ID":{"name":"Idaho","pop_2014":1634464,"W1":5,"W2":7,"W3":6,"W4":5,"W5":6,"W6":4,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":2,"W49":1,"W50":1,"W51":3,"W52":1},"IL":{"name":"Illinois","pop_2014":12880580,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":2,"W49":3,"W50":6,"W51":10,"W52":10},"IN":{"name":"Indiana","pop_2014":6596855,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":2,"W45":1,"W46":1,"W47":1,"W48":3,"W49":4,"W50":3,"W51":9,"W52":10},"IA":{"name":"Iowa","pop_2014":3107126,"W1":5,"W2":8,"W3":9,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":2,"W50":2,"W51":3,"W52":8},"KS":{"name":"Kansas","pop_2014":2904021,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":2,"W48":1,"W49":3,"W50":7,"W51":10,"W52":10},"KY":{"name":"Kentucky","pop_2014":4413457,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":3,"W47":2,"W48":3,"W49":6,"W50":10,"W51":10,"W52":10},"LA":{"name":"Louisiana","pop_2014":4649676,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":3,"W41":3,"W42":4,"W43":5,"W44":7,"W45":7,"W46":8,"W47":10,"W48":10,"W49":10,"W50":10,"W51":10,"W52":10},"ME":{"name":"Maine","pop_2014":1330089,"W1":1,"W2":1,"W3":1,"W4":1,"W5":1,"W6":3,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":1,"W50":1,"W51":1,"W52":1},"MD":{"name":"Maryland","pop_2014":5976407,"W1":4,"W2":6,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":1,"W50":1,"W51":2,"W52":7},"MA":{"name":"Massachusetts","pop_2014":6745408,"W1":7,"W2":5,"W3":8,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":2,"W45":2,"W46":2,"W47":3,"W48":3,"W49":3,"W50":4,"W51":5,"W52":8},"MI":{"name":"Michigan","pop_2014":9909877,"W1":5,"W2":8,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":2,"W46":1,"W47":2,"W48":2,"W49":3,"W50":3,"W51":5,"W52":6},"MN":{"name":"Minnesota","pop_2014":5457173,"W1":7,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":2,"W50":2,"W51":4,"W52":5},"MS":{"name":"Mississippi","pop_2014":2994079,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":2,"W41":1,"W42":1,"W43":3,"W44":4,"W45":8,"W46":10,"W47":10,"W48":10,"W49":10,"W50":10,"W51":10,"W52":10},"MO":{"name":"Missouri","pop_2014":6063589,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":3,"W50":5,"W51":10,"W52":10},"MT":{"name":"Montana","pop_2014":1023579,"W1":1,"W2":2,"W3":2,"W4":1,"W5":2,"W6":1,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":1,"W50":1,"W51":1,"W52":1},"NE":{"name":"Nebraska","pop_2014":1881503,"W1":10,"W2":6,"W3":9,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":2,"W43":2,"W44":2,"W45":3,"W46":3,"W47":5,"W48":3,"W49":3,"W50":6,"W51":8,"W52":10},"NV":{"name":"Nevada","pop_2014":2839099,"W1":9,"W2":7,"W3":6,"W4":6,"W5":8,"W6":8,"W40":1,"W41":1,"W42":1,"W43":1,"W44":2,"W45":2,"W46":2,"W47":2,"W48":2,"W49":3,"W50":5,"W51":6,"W52":9},"NH":{"name":"New Hampshire","pop_2014":1326813,"W1":4,"W2":4,"W3":8,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":1,"W50":1,"W51":1,"W52":1},"NJ":{"name":"New Jersey","pop_2014":8938175,"W1":9,"W2":8,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":2,"W45":2,"W46":2,"W47":3,"W48":3,"W49":3,"W50":4,"W51":5,"W52":8},"NM":{"name":"New Mexico","pop_2014":2085572,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":2,"W46":3,"W47":3,"W48":1,"W49":3,"W50":5,"W51":7,"W52":10},"NY":{"name":"New York","pop_2014":19746227,"W1":7,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":1,"W50":2,"W51":5,"W52":4},"NC":{"name":"North Carolina","pop_2014":9943964,"W1":5,"W2":9,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":2,"W47":3,"W48":1,"W49":2,"W50":1,"W51":1,"W52":6},"ND":{"name":"North Dakota","pop_2014":739482,"W1":2,"W2":6,"W3":4,"W4":4,"W5":5,"W6":7,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":1,"W50":1,"W51":5,"W52":2},"OH":{"name":"Ohio","pop_2014":11594163,"W1":5,"W2":6,"W3":8,"W4":8,"W5":9,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":1,"W50":1,"W51":2,"W52":6},"OK":{"name":"Oklahoma","pop_2014":3878051,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":2,"W45":3,"W46":3,"W47":4,"W48":4,"W49":4,"W50":10,"W51":10,"W52":10},"OR":{"name":"Oregon","pop_2014":3970239,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":9,"W40":1,"W41":1,"W42":1,"W43":1,"W44":2,"W45":2,"W46":2,"W47":3,"W48":3,"W49":4,"W50":5,"W51":9,"W52":10},"PA":{"name":"Pennsylvania","pop_2014":12787209,"W1":6,"W2":7,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":2,"W45":2,"W46":2,"W47":2,"W48":2,"W49":2,"W50":3,"W51":3,"W52":6},"RI":{"name":"Rhode Island","pop_2014":1055173,"W1":5,"W2":7,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":3,"W50":2,"W51":3,"W52":2},"SC":{"name":"South Carolina","pop_2014":4832482,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":2,"W41":1,"W42":2,"W43":5,"W44":6,"W45":6,"W46":6,"W47":10,"W48":10,"W49":10,"W50":10,"W51":10,"W52":10},"SD":{"name":"South Dakota","pop_2014":853175,"W1":6,"W2":7,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":2,"W42":2,"W43":3,"W44":3,"W45":4,"W46":6,"W47":4,"W48":4,"W49":4,"W50":4,"W51":5,"W52":8},"TN":{"name":"Tennessee","pop_2014":6549352,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":1,"W50":2,"W51":9,"W52":7},"TX":{"name":"Texas","pop_2014":26956958,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":3,"W45":3,"W46":5,"W47":5,"W48":7,"W49":9,"W50":10,"W51":10,"W52":10},"UT":{"name":"Utah","pop_2014":2942902,"W1":3,"W2":4,"W3":5,"W4":3,"W5":4,"W6":6,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":1,"W50":1,"W51":1,"W52":4},"VT":{"name":"Vermont","pop_2014":626562,"W1":4,"W2":5,"W3":7,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":1,"W50":1,"W51":1,"W52":3},"VA":{"name":"Virginia","pop_2014":8326289,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":2,"W43":2,"W44":2,"W45":3,"W46":3,"W47":4,"W48":4,"W49":4,"W50":5,"W51":6,"W52":9},"WA":{"name":"Washington","pop_2014":7061530,"W1":10,"W2":10,"W3":8,"W4":9,"W5":7,"W6":5,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":1,"W50":1,"W51":1,"W52":10},"WV":{"name":"West Virginia","pop_2014":1850326,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":3,"W48":1,"W49":1,"W50":5,"W51":9,"W52":10},"WI":{"name":"Wisconsin","pop_2014":5757564,"W1":7,"W2":8,"W3":7,"W4":9,"W5":10,"W6":9,"W40":1,"W41":1,"W42":1,"W43":1,"W44":1,"W45":1,"W46":1,"W47":1,"W48":1,"W49":2,"W50":1,"W51":4,"W52":5},"WY":{"name":"Wyoming","pop_2014":584153,"W1":10,"W2":10,"W3":10,"W4":10,"W5":10,"W6":10,"W40":1,"W41":3,"W42":1,"W43":3,"W44":3,"W45":2,"W46":1,"W47":1,"W48":2,"W49":3,"W50":3,"W51":5,"W52":10}} | |
const width = 600 | |
const height = 400 | |
const scale = 0.64 | |
const colorScale = d3.scaleLinear().domain([0, 10]).range(['#feebe2', '#c51b8a']) | |
function interpolateEachNode (node) { | |
const circle = pseudocircle(node) | |
const closestPoints = node.rings.slice(1).map(function (ring) { | |
const i = d3.scan(circle.map(point => distance(point, ring.centroid))) | |
return ring.map(() => circle[i]) | |
}) | |
const interpolator = d3.interpolateArray(node.rings, [circle, ...closestPoints]) | |
node.interpolator = function (t) { | |
const str = pathString(interpolator(t)) | |
// Prevent some fill-rule flickering for MultiPolygons | |
if (t > 0.99) { | |
return str.split('Z')[0] + 'Z' | |
} | |
return str | |
} | |
} | |
function displayTextNodes (g, show) { | |
return () => { | |
const display = show ? 'block' : 'none' | |
g.selectAll('text').style('display', display) | |
} | |
} | |
function pseudocircle (node) { | |
return node.rings[0].map(point => { | |
var angle = node.startingAngle - 2 * Math.PI * (point.along / node.perimeter) | |
return [ | |
Math.cos(angle) * node.r + node.x, | |
Math.sin(angle) * node.r + node.y | |
] | |
}) | |
} | |
function cleanUpGeometry (node) { | |
node.rings = (node.geometry.type === 'Polygon' ? [node.geometry.coordinates] : node.geometry.coordinates) | |
node.rings = node.rings.map(polygon => { | |
polygon[0].area = d3.polygonArea(polygon[0]) | |
polygon[0].centroid = d3.polygonCentroid(polygon[0]) | |
return polygon[0] | |
}) | |
node.rings.sort((a, b) => b.area - a.area) | |
node.perimeter = d3.polygonLength(node.rings[0]) | |
// Optional step, but makes for more circular circles | |
bisect(node.rings[0], node.perimeter / 72) | |
node.rings[0].reduce(function (prev, point) { | |
point.along = prev ? prev.along + distance(point, prev) : 0 | |
node.perimeter = point.along | |
return point | |
}, null) | |
node.startingAngle = Math.atan2(node.rings[0][0][1] - node.y0, node.rings[0][0][0] - node.x0) | |
} | |
function bisect (ring, maxSegmentLength) { | |
for (var i = 0; i < ring.length; i++) { | |
const a = ring[i] | |
let b = i === ring.length - 1 ? ring[0] : ring[i + 1] | |
while (distance(a, b) > maxSegmentLength) { | |
b = midpoint(a, b) | |
ring.splice(i + 1, 0, b) | |
} | |
} | |
} | |
function distance (a, b) { | |
return Math.sqrt((a[0] - b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1])) | |
} | |
function midpoint (a, b) { | |
return [a[0] + (b[0] - a[0]) * 0.5, a[1] + (b[1] - a[1]) * 0.5] | |
} | |
function pathString (d) { | |
return (d.rings || d).map(ring => 'M' + ring.join('L') + 'Z').join(' ') | |
} | |
function applyLabelToNodes (g, nodes) { | |
// apply state labels | |
g.selectAll('g') | |
.data(nodes) | |
.enter() | |
.append('text') | |
.text(d => { | |
if (d.r > 14) { | |
return d.id | |
} | |
}) | |
.attr('text-anchor', 'middle') | |
.attr('y', d => d.y + 5) | |
.attr('x', d => d.x) | |
.attr('class', 'state-label') | |
.style('display', 'none') | |
} | |
function updateNodesForWeek (val) { | |
return (d, i) => { | |
const state = statesJson[d.id] | |
const colorNum = state[`W${val}`] | |
return colorScale(colorNum) | |
} | |
} | |
function createSimulation (nodes, links, width, height) { | |
return d3.forceSimulation(nodes) | |
.force('cx', d3.forceX().x(d => width / 2).strength(0.02)) | |
.force('cy', d3.forceY().y(d => height / 2).strength(0.02)) | |
.force('link', d3.forceLink(links).distance(d => d.distance)) | |
.force('x', d3.forceX().x(d => d.x).strength(0.1)) | |
.force('y', d3.forceY().y(d => d.y).strength(0.1)) | |
.force('collide', d3.forceCollide().strength(0.8).radius(d => d.r + 1)) | |
.stop() | |
} | |
function setupNodeData (node, i) { | |
const centroid = d3.geoPath().centroid(node) | |
const radius = d3.scaleSqrt().range([0, 75]).clamp(true) | |
node.x0 = centroid[0] | |
node.y0 = centroid[1] | |
const state = statesJson[node.id] || {} | |
node.stateName = state.name | |
node.r = radius(state.pop_2014 / 35000000) | |
cleanUpGeometry(node) | |
} | |
function updateWeekLabel (text) { | |
return () => { | |
d3.select('.week-label').text(text) | |
} | |
} | |
function initMap(selector = '#cartogram') { | |
d3.select(selector) | |
.append('p') | |
.attr('class', 'week-label') | |
const svg = d3.select(selector).append('svg') | |
.attr('width', width) | |
.attr('height', height) | |
.attr('id', 'map-svg') | |
.attr('viewBox', `0 0 ${width} ${height}`) | |
d3.json('us-topo.json', (err, us) => { | |
if (err) { throw Error(err) } | |
const neighbors = topojson.neighbors(us.objects.states.geometries) | |
const nodes = topojson.feature(us, us.objects.states).features | |
nodes.forEach(setupNodeData) | |
const g = svg.append('g') | |
.attr('transform', `scale(${scale}) translate(0, 0)`) | |
.attr('id', 'states') | |
const states = g.selectAll('g') | |
.data(nodes) | |
.enter() | |
.append('path') | |
.attr('d', pathString) | |
.attr('fill', '#eee') | |
d3.select(selector) | |
.append('p') | |
.text('Source: CDC') | |
.attr('class', 'credit') | |
simulate() | |
function simulate () { | |
nodes.forEach(node => { | |
node.x = node.x0 | |
node.y = node.y0 | |
}) | |
const links = d3.merge(neighbors.map(function (neighborSet, i) { | |
return neighborSet.filter(j => nodes[j]).map(function (j) { | |
return {source: i, target: j, distance: nodes[i].r + nodes[j].r + 3} | |
}) | |
})) | |
const simulation = createSimulation(nodes, links, width, height) | |
while (simulation.alpha() > 0.1) { | |
simulation.tick() | |
} | |
nodes.forEach(interpolateEachNode) | |
applyLabelToNodes(g, nodes) | |
const transDelay = 600 | |
const transDuration = 900 | |
states.sort((a, b) => b.r - a.r) | |
.transition().on('start', updateWeekLabel('Oct 7th, 2017')) | |
.attr('fill', '#eee') | |
.delay(transDelay).duration(transDuration) // change to circles | |
.attrTween('d', node => node.interpolator) | |
.on('end', displayTextNodes(g, true)) | |
.transition() | |
.delay(transDelay) | |
.duration(transDuration) | |
.attr('fill', updateNodesForWeek(40)) | |
.transition().on('start', updateWeekLabel('Nov 4th, 2017')) | |
.delay(transDelay) | |
.duration(transDuration) | |
.attr('fill', updateNodesForWeek(44)) | |
.transition().on('start', updateWeekLabel('Dec 2nd, 2017')) | |
.delay(transDelay) | |
.duration(transDuration) | |
.attr('fill', updateNodesForWeek(48)) | |
.transition().on('start', updateWeekLabel('Dec 30th 2017')) | |
.delay(transDelay) | |
.duration(transDuration) | |
.attr('fill', updateNodesForWeek(52)) | |
.transition().on('start', updateWeekLabel('Jan 13, 2018')) | |
.delay(transDelay) | |
.duration(transDuration) | |
.attr('fill', updateNodesForWeek(2)) | |
.transition().on('start', updateWeekLabel('Feb 10, 2018')) | |
.delay(transDelay) | |
.duration(transDuration) | |
.attr('fill', updateNodesForWeek(6)) | |
.transition() | |
.on('start', displayTextNodes(g, false)) | |
.delay(transDelay) // back to states | |
.attrTween('d', node => t => node.interpolator(1 - t)) | |
.on('end', (d, i) => i || simulate()) | |
} | |
}) | |
} | |
initMap() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment