// Compute the dimensions; the width is provided by Observable.
const width = 1000;
const height = Math.min(500, width / 2);
const outerRadius = height / 2 - 10;
const innerRadius = outerRadius * 0.75;
// https://tauday.com/tau-manifesto
const tau = 2 * Math.PI;
// Create the SVG container, and apply a transform such that the origin is the
// center of the canvas. This way, we don’t need to position arcs individually.
const svg = d3.select("svg")
.attr("viewBox", [0, 0, width, height]);
const g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
// An arc function with all values bound except the endAngle. So, to compute an
// SVG path string for a given angle, we pass an object with an endAngle
// property to the arc function, and it will return the corresponding string.
const arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius)
.startAngle(0)
.cornerRadius(30);
// Add the background arc, from 0 to 100% (tau).
const background = g.append("path")
.datum({endAngle: tau})
.style("fill", "#ddd")
.attr("d", arc);
// Add the foreground arc in orange, currently showing 12.7%.
const foreground = g.append("path")
.datum({endAngle: 0.25 * tau})
.style("fill", "orange")
.attr("d", arc);
<svg width="500" height="500" />
body{
height: 1000px;
}