Published
Edited
Oct 22, 2021
26 forks
50 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
alphabet = [..."ABCDEFGHIJKLMNOPQRSTUVWXYZ"]
Insert cell
chart1 = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, 33])
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.style("display", "block");

svg.selectAll("text")
.data(alphabet)
.join("text")
.attr("x", (d, i) => i * 17)
.attr("y", 17)
.attr("dy", "0.35em")
.text(d => d);

return svg.node();
}
Insert cell
Insert cell
htl.html`<svg viewBox="0 0 ${width} 33" font-family="sans-serif" font-size="10" style="display: block;">
${alphabet.map((d, i) => htl.svg`<text x="${i * 17}" y="17" dy="0.35em">${d}</text>`)}
</svg>`
Insert cell
Insert cell
randomLetters = {
while (true) {
yield d3.shuffle(alphabet.slice())
.slice(Math.floor(Math.random() * 10) + 5)
.sort(d3.ascending);
await Promises.delay(3000);
}
}
Insert cell
chart2 = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, 33])
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.style("display", "block");

let text = svg.selectAll("text");

return Object.assign(svg.node(), {
update(letters) {
text = text
.data(letters)
.join("text")
.attr("x", (d, i) => i * 17)
.attr("y", 17)
.attr("dy", "0.35em")
.text(d => d);
}
});
}
Insert cell
chart2.update(randomLetters)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
chart3 = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, 33])
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.style("display", "block");

let text = svg.selectAll("text");

return Object.assign(svg.node(), {
update(letters) {
text = text
.data(letters, d => d)
.join(
enter => enter.append("text")
.attr("y", 17)
.attr("dy", "0.35em")
.text(d => d),
update => update,
exit => exit.remove()
)
.attr("x", (d, i) => i * 17);
}
});
}
Insert cell
chart3.update(randomLetters)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
chart4 = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, 33])
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.style("display", "block");

let text = svg.selectAll("text");

return Object.assign(svg.node(), {
update(letters) {
const t = svg.transition().duration(750);

text = text
.data(letters, d => d)
.join(
enter => enter.append("text")
.attr("y", -7)
.attr("dy", "0.35em")
.attr("x", (d, i) => i * 17)
.text(d => d),
update => update,
exit => exit
.call(text => text.transition(t).remove()
.attr("y", 41))
)
.call(text => text.transition(t)
.attr("y", 17)
.attr("x", (d, i) => i * 17));
}
});
}
Insert cell
chart4.update(randomLetters)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

// For the initial render, reference the current age non-reactively.
const agedata = viewof agedata.value;

const x = d3.scaleLinear()
.domain([0, d3.max(agedata, d => d.value)])
.rangeRound([margin.left, width - margin.right]);

const y = d3.scaleBand()
.domain(agedata.map(d => d.name))
.rangeRound([margin.top, margin.top + 20 * data.names.length]);

let bar = svg.append("g")
.attr("fill", "steelblue")
.selectAll("rect")
.data(agedata, d => d.name)
.join("rect")
.style("mix-blend-mode", "multiply")
.attr("x", x(0))
.attr("y", d => y(d.name))
.attr("width", d => x(d.value) - x(0))
.attr("height", y.bandwidth() - 1);

const gx = svg.append("g")
.call(xAxis, x);

const gy = svg.append("g")
.call(yAxis, y);

return Object.assign(svg.node(), {
update(agedata) {
const t = svg.transition().duration(750);

gx.transition(t)
.call(xAxis, x.domain([0, d3.max(agedata, d => d.value)]));

gy.transition(t)
.call(yAxis, y.domain(agedata.map(d => d.name)));

bar = bar
.data(agedata, d => d.name)
.call(bar => bar.transition(t)
.attr("width", d => x(d.value) - x(0))
.attr("y", d => y(d.name)));
}
});
}
Insert cell
chart.update(agedata)
Insert cell
Insert cell
Insert cell
Insert cell
data = {
const data = await FileAttachment("us-population-state-age.csv").csv();
const ages = data.columns.slice(1);
const totals = new Map(data.map(d => [d.name, d3.sum(ages, age => d[age])]));
return Object.assign(d3.cross(data, ages).map(([d, age]) => ({name: d.name, age, value: +d[age] / totals.get(d.name)})), {names: data.map(d => d.name), ages});
}
Insert cell
xAxis = (g, x) => g
.attr("transform", `translate(0,${margin.top})`)
.call(d3.axisTop(x).ticks(width / 80, "%"))
.call(g => (g.selection ? g.selection() : g).select(".domain").remove())
Insert cell
yAxis = (g, y) => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y).tickSizeOuter(0))
Insert cell
height = margin.top + 20 * 10
Insert cell
margin = ({top: 30, right: 20, bottom: 0, left: 30})
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