Published
Edited
Jul 20, 2021
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
x = d3.scaleBand()
.domain(data.map(d => d.State))
.range([0, 2 * Math.PI])
.align(0)
Insert cell
// This scale maintains area proportionality of radial bars
y = d3.scaleRadial()
.domain([0, d3.max(data, d => d.total)])
.range([innerRadius, outerRadius])
Insert cell
z = d3.scaleOrdinal()
.domain(data.columns.slice(1))
.range(["#665eb2", "#665eb2", "#665eb2", "#665eb2", "##665eb2", "#665eb2", "#4e4e4e"])
Insert cell
xAxis = g => g
.attr("text-anchor", "middle")
.call(g => g.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", d => `
rotate(${((x(d.State) + x.bandwidth() / 2) * 180 / Math.PI - 90)})
translate(${innerRadius},0)
`)
.call(g => g.append("line")
.attr("x2", -5)
.attr("stroke", "#000"))
.call(g => g.append("text")
.attr("transform", d => (x(d.State) + x.bandwidth() / 2 + Math.PI / 2) % (2 * Math.PI) < Math.PI
? "rotate(90) translate(0,16)"
: "rotate(-90) translate(0,-9)")
.text(d => d.State)))
Insert cell
yAxis = g => g
.attr("text-anchor", "end")
.call(g => g.append("text")
.attr("x", -6)
.attr("y", d => -y(y.ticks(10).pop()))
.attr("dy", "-1em")
.text("Percent recovered"))
.call(g => g.selectAll("g")
.data(y.ticks(10).slice(1))
.join("g")
.attr("fill", "none")
.call(g => g.append("circle")
.attr("stroke", "#000")
.attr("stroke-opacity", 0.5)
.attr("r", y))
.call(g => g.append("text")
.attr("x", -6)
.attr("y", d => -y(d))
.attr("dy", "0.35em")
.attr("stroke", "#fff")
.attr("stroke-width", 5)
.text(y.tickFormat(10, "s"))
.clone(true)
.attr("fill", "#000")
.attr("stroke", "none")))
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