Published
Edited
Jan 30, 2021
1 fork
1 star
Insert cell
Insert cell
groups = ["<10", "10-19", "20-29", "30-39", "40-49", "50-59", "60-69", "70-79", "≥80"]
Insert cell
Insert cell
{
const form = html`<form onsubmit="return false;">`;
for(const group of groups) {
// giving them index names because having their names be numbers was wonky
const all_buttons = form.appendChild(html`<button name=group_${groups.indexOf(group)}> ${group} </button>`)
}
/* todo: get fancy and operationalize this */
form.group_0.onclick = () => {
chart.changeColor('<10');
};
form.group_1.onclick = () => {
chart.changeColor('10-19');
};
form.group_2.onclick = () => {
chart.changeColor('20-29');
};
form.group_3.onclick = () => {
chart.changeColor('30-39');
};
form.group_4.onclick = () => {
chart.changeColor('40-49');
};
form.group_5.onclick = () => {
chart.changeColor('50-59');
};
form.group_6.onclick = () => {
chart.changeColor('60-69');
};
form.group_7.onclick = () => {
chart.changeColor('70-79');
};
form.group_8.onclick = () => {
chart.changeColor('≥80');
};

return form;
}
Insert cell
viewof chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);
svg.append("g")
.selectAll("g")
.data(series)
.join("g")
.attr("fill", d => color(d.key))
.selectAll("rect")
.data(d => d)
.join("rect")
.attr("x", (d, i) => x(d.data.name))
.attr("y", d => y(d[1]))
.attr("height", d => y(d[0]) - y(d[1]))
.attr("width", x.bandwidth())
.append("title")
.text(d => `${d.data.name} ${d.key}
${formatValue(d.data[d.key])}`);

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

svg.append("g")
.call(yAxis);
// rather than change the entire plot color
// we need to just change the color of the selected group
function changeColor(grp) {
/// we're definitely getting the grp name from the buttom
console.log(grp)
svg
.selectAll("rect")
.transition()
.duration(2000)
// sanity check: this works to change the whole plot
//.attr("fill", "yellow")
// color the selected group yellow based on d.key
// ....but this doesn't work
.attr("fill", function(d) {
console.log(d.key === grp ? "yellow" : color(d.key))
return (d.key === grp ? "yellow" : color(d.key))
})
}
// export the changeColor function in the SVG's .value property
svg.node().value = { changeColor };

return svg.node();
}
Insert cell
series
Insert cell
data = d3.csvParse(await FileAttachment("us-population-state-age.csv").text(), (d, i, columns) => (d3.autoType(d), d.total = d3.sum(columns, c => d[c]), d)).sort((a, b) => b.total - a.total)
Insert cell
series = d3.stack()
.keys(data.columns.slice(1))
(data)
.map(d => (d.forEach(v => v.key = d.key), d))
Insert cell
x = d3.scaleBand()
.domain(data.map(d => d.name))
.range([margin.left, width - margin.right])
.padding(0.1)
Insert cell
y = d3.scaleLinear()
.domain([0, d3.max(series, d => d3.max(d, d => d[1]))])
.rangeRound([height - margin.bottom, margin.top])
Insert cell
color = d3.scaleOrdinal()
.domain(series.map(d => d.key))
.range(d3.schemeGreys[series.length])
.unknown("#ccc")
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x).tickSizeOuter(0))
.call(g => g.selectAll(".domain").remove())
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y).ticks(null, "s"))
.call(g => g.selectAll(".domain").remove())
Insert cell
formatValue = x => isNaN(x) ? "N/A" : x.toLocaleString("en")
Insert cell
height = 600
Insert cell
margin = ({top: 10, right: 10, bottom: 20, left: 40})
Insert cell
d3 = require("d3@6")
Insert cell
import {legend} from "@d3/color-legend"
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