Published
Edited
Oct 13, 2021
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
chart = {
const svg = d3.select(DOM.svg(chartWidth, height));

let counter = 1;

svg.append("g").call(xAxis);

svg
.append("g")
.attr("class", "yAxis")
.call(yAxis)
.call(g =>
g
.selectAll(".tick text")
.attr("font-size", 12)
.attr("y", -3)
);



const group = svg
.append("g")
.selectAll("g")
.data(data.series)
.join("g")
.attr("transform", d => `translate(0,${y(d.name) + 1})`)
.on("click", function(d,i,nodes) {
console.log(d3.select(this).data()[0].name);
console.log(d3.selectAll('g.yAxis text').data()[0]);
let odd = counter % 2 === 1;
if (odd) {
d3.selectAll('path.partArea').attr('opacity', 0.2);
d3.selectAll('path.partLine').attr('opacity', 0.2);
d3.selectAll('g.yAxis text').attr('opacity', 0.2);
d3.selectAll('g.yAxis text').filter(d => d == d3.select(this).data()[0].name).attr('fill', 'green').attr('opacity',1);
d3.select(this).select('path.partArea').attr('fill', 'green');
d3.select(this).select('path.partArea').attr('opacity', 1);
d3.select(this)
.append("g")
.attr("class", "zAxis")
.call(zAxis);
}else{
d3.selectAll("g.zAxis").remove();
d3.selectAll('path.partArea').attr('opacity', fillOpacity);
d3.selectAll('path.partLine').attr('opacity', fillOpacity);
d3.selectAll('g.yAxis text').attr('opacity', 1).attr('fill', 'black');
d3.select(this).select('path.partArea').attr('fill', fillColor);
}
counter++;
});

group
.append("path")
.attr("class", "partArea")
.attr("fill", fillColor)
.attr("opacity", fillOpacity)
.attr("d", d => area(d.values));

group
.append("path")
.attr("class", "partLine")
.attr("fill", "none")
.attr("stroke", strokeColor)
.attr("d", 0)
.attr("d", d => line(d.values));

return svg.node();
}
Insert cell
Insert cell
chartWidth = Math.min(640, width)
Insert cell
height = 2800
Insert cell
margin = ({top: 80, right: 40, bottom: 30, left: 140})
Insert cell
fillColor = '#94c1cf'
Insert cell
strokeColor = '#707070'
Insert cell
viewof fillOpacity = slider({
value: 0.7,
step: 0.1,
title: "Fill opacity"
})
Insert cell
viewof overlap = slider({
value: 5,
min: 1,
max: 20,
step: 1,
title: "Overlap"
})
Insert cell
x = d3
.scaleTime()
.domain(d3.extent(data.dates))
.range([margin.left, chartWidth - margin.right])
Insert cell
y = d3.scalePoint()
.domain(data.series.map(d => d.name))
.range([margin.top, height - margin.bottom])
Insert cell
z = d3.scaleLinear()
.domain([0, d3.max(data.series, d => d3.max(d.values))]).nice()
.range([0, -overlap * y.step()])
Insert cell
xAxis = g =>
g.attr("transform", `translate(0,${height - margin.bottom})`).call(
d3
.axisBottom(x)
.ticks(chartWidth / 80)
.tickSizeOuter(0)
)
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y).tickSize(0).tickPadding(4))
.call(g => g.select(".domain").remove())
Insert cell
zAxis = g => g
.attr("transform", `translate(${chartWidth - margin.right},0)`)
.call(d3.axisRight(z)
.ticks(4)
.tickSize(`${-(chartWidth - margin.left - margin.right - 10)}`)
.tickFormat(d3.format('.2s')))
.call(g => g.select(".domain").remove())
Insert cell
area = d3.area()
.curve(d3.curveBasis)
.defined(d => !isNaN(d))
.x((d, i) => x(data.dates[i]))
.y0(0)
.y1(d => z(d))
Insert cell
line = area.lineY1()
Insert cell
data = {
let data = varSort === "Sort by Alphabet" ?
JSON.parse(JSON.stringify(raw)) :
JSON.parse(JSON.stringify(raw)).sort((a,b) => b[varSelector] - a[varSelector]);
data.forEach(d => {
d.date = dateParse(d.date);
d.value = +d[varSelector];
});
const dates = Array.from(d3.group(data, d => +d.date).keys()).sort(
d3.ascending
);
return {
dates: dates.map(d => new Date(d)),
series: d3
.groups(data, d => d.country)
.map(([name, values]) => {
const value = new Map(values.map(d => [+d.date, d.value]));
return { name, values: dates.map(d => value.get(d)) };
})
};
}
Insert cell
raw = aq.from(raw_data)
.join(aq.from(raw_country).select('country', 'population'), ['country', 'country'])
.derive({new_cases_per_1m: d => (d.daily_new_cases / d.population) * 1000000,
new_deaths_per_1m: d => (d.daily_new_deaths / d.population) * 1000000,
active_cases_per_1m: d => (d.active_cases / d.population) * 1000000
})
.objects()
Insert cell
raw_data = d3.csv('https://raw.githubusercontent.com/zhihaohowardyao/Howard/master/data/worldometer_coronavirus_daily_data.csv')
Insert cell
raw_country = d3.csv('https://raw.githubusercontent.com/zhihaohowardyao/Howard/master/data/worldometer_coronavirus_summary_data.csv')
Insert cell
dateParse = d3.timeParse("%Y-%m-%d")
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more