function drawChart() { class Disease { constructor(name, min, max, year=null) { this.name = name; this.range = { min: min, max: max }; this.year = year; diseaseArray.push(this); } } let diseaseArray = []; let covid = new Disease('COVID-19', 2, 2.5) let measles = new Disease('Measles', 12, 18) let mumps = new Disease('Mumps', 4, 7) let flu1918 = new Disease('1918 Flu Pandemic', 2, 3) let sars = new Disease('SARS', 2, 5) let ebola = new Disease('Ebola virus', 1.5, 2.4, 2014) let h1n1 = new Disease('H1N1 influenza', 1.46, 1.48, 2009) let mers = new Disease('MERS', 0.3, 0.8) let rubella = new Disease('Rubella', 6, 7) let polio = new Disease('Polio', 5, 7) let smallpox = new Disease('Smallpox', 5, 7) let diseaseMaxRange = Math.max.apply(Math, diseaseArray.map(function(d) { return d.range.max; })); let diseaseMaxRound = Math.ceil(diseaseMaxRange/10)*10 + 1; var myScale = d3.scaleLinear() .domain([0, diseaseMaxRound]) .range([0, 500]); let container = d3.select('#covid-spread-chart') let svg = container.append('svg') .attr('width', '100%') .attr('viewBox', '0 0 800 380') .attr('class', 'covid-svg') let chartLayer = svg.append('g').attr('transform', `translate(0, 40)`) let chartTitle = svg.append('text').attr('class', 'chart-title text-bold') chartTitle.text('Expected number of people a patient will infect, by disease') .attr('x', 15) .attr('y', 20) let bar = { h: 28, pad: { x: 2, y: 2 }, color: { light: '#e89da2', dark: '#c9485b', bg: '#f7f6f2' } } let scaleLayer = svg.append('g').attr('transform', `translate(460, 355)`) scaleLayer.append('rect') .attr('x', 0) .attr('y', 0) .attr('width', bar.h - bar.pad.x) .attr('height', bar.h - bar.pad.y) .attr('fill', bar.color.dark) scaleLayer.append('text') .attr('class', 'text-legend') .attr('x', bar.h + 2) .attr('y', bar.h/2 + 6 -3) .attr('text-anchor', 'start') .text('Minimum spread') scaleLayer.append('rect') .attr('x', 160) .attr('y', 0) .attr('width', bar.h - bar.pad.x) .attr('height', bar.h - bar.pad.y) .attr('fill', bar.color.light) scaleLayer.append('text') .attr('class', 'text-legend') .attr('x', 160 + bar.h + 2) .attr('y', bar.h/2 + 6 -3) .attr('text-anchor', 'start') .text('Maximum spread') let diseaseLayer = chartLayer.selectAll('g').data(diseaseArray).enter().append('g') .attr('transform', (d, i) => `translate(175, ${i*bar.h})`) diseaseLayer.append('text') .attr('class', 'text-bold') .attr('x', -15) .attr('y', bar.h/2 + 6 -1) .attr('text-anchor', 'end') .text(d => d.name) for (let j = 0; j < diseaseMaxRound; j++) { diseaseLayer.append('rect') .attr('x', (d, i) => j * (bar.h + 1)) .attr('y', 0) .attr('width', bar.h - bar.pad.x) .attr('height', bar.h - bar.pad.y) .attr('fill', bar.color.bg) } function fillChart(){ for (let j = 0; j < diseaseMaxRound; j++) { diseaseLayer.append('rect') .attr('x', (d, i) => j * (bar.h + 1)) .attr('y', 0) .attr('width', (d, i) => { if (d.range.max - j >= 1 ) { return bar.h - bar.pad.x } else if (d.range.max - j < 1) { return (d.range.max - j)*(bar.h - bar.pad.x) } else { return 0; } }) .attr('height', bar.h - bar.pad.y) .attr('fill', d => j > d.range.max ? '#ffffff00' : bar.color.light) .attr('opacity', 0) .transition().duration(100).delay(j*100) .attr('opacity', 1) } for (let j = 0; j < diseaseMaxRound; j++) { diseaseLayer.append('rect') .attr('x', (d, i) => j * (bar.h + 1)) .attr('y', 0) .attr('width', (d, i) => { if (d.range.min - j >= 1 ) { return bar.h - bar.pad.x } else if (d.range.min - j < 1) { return (d.range.min - j)*(bar.h - bar.pad.x) } else { return 0; } }) .attr('height', bar.h - bar.pad.y) .attr('fill', d => j > d.range.min ? '#ffffff00' : bar.color.dark) .attr('opacity', 0) .transition().duration(100).delay(j*100) .attr('opacity', 1) } diseaseLayer.append('text') .attr('class', 'text-range bold') .attr('x', d => d.range.max * (bar.h + 1) + 3) .attr('y', bar.h/2 + 6 -1) .attr('text-anchor', 'start') .text(d => `${d.range.min} - ${d.range.max}`) .attr('opacity', 0) .transition().delay(d=> d.range.max*100) .attr('opacity', 1) } const target = document.querySelectorAll('#covid-spread-chart'); const config = { //rootMargin: '250px 0 150px 0', threshold: [0.5] }; observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.intersectionRatio > 0) { fillChart() observer.unobserve(entry.target); } }); }, config); target.forEach(targ => { observer.observe(targ); }); } window.onload = function() { if (document.getElementById('covid-spread-chart')) { drawChart(); } }