Skip to content

Instantly share code, notes, and snippets.

@wonga00
Last active September 15, 2017 05:08
Show Gist options
  • Save wonga00/2c0c6458738968f5cc74806bc9251a36 to your computer and use it in GitHub Desktop.
Save wonga00/2c0c6458738968f5cc74806bc9251a36 to your computer and use it in GitHub Desktop.
Labeling arcs at the midpoint
<script src="https://d3js.org/d3.v4.min.js"></script>
<body>
<script>
let width = 300;
let height = 300;
let svg = d3.select('body').append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', `translate(${width * 0.5}, ${height * 0.5})`);
let outerRadius = 0.8 * width * 0.5,
innerRadius = 0.6 * width * 0.5;
let data = [
{
startAngle: 0,
endAngle: Math.PI * 1,
name: "Cow"
},
{
startAngle: Math.PI * 1,
endAngle: Math.PI * 1.2,
name: "Banana"
},
{
startAngle: Math.PI * 1.2,
endAngle: Math.PI * 1.8,
name: "Apple"
},
{
startAngle: Math.PI * 1.8,
endAngle: Math.PI * 2,
name: "This is a long one"
}
];
let color = d3.scaleOrdinal(d3.schemeCategory10);
let arc = d3.arc()
.outerRadius(outerRadius)
.innerRadius(innerRadius)
.startAngle(d => d.startAngle)
.endAngle(d => d.endAngle);
let bars = svg.selectAll('.bar').data(data);
let barsEnter = bars.enter()
.append('path')
.attr('class', 'bar')
bars.merge(barsEnter)
.attr('d', d => arc(d))
.attr('fill', d => color(d.name))
// create arcs that wrap around the entire circle and have the midpoint
// at the angle we want to center the text on
let textArcData = data.map(d => {
let angle = (d.startAngle + d.endAngle) * 0.5;
if (angle > Math.PI / 2 && angle < Math.PI * 3 / 2) {
return {
startAngle: angle + Math.PI,
endAngle: angle - Math.PI,
lowerHalf: true,
name: d.name
}
} else {
return {
startAngle: angle - Math.PI,
endAngle: angle + Math.PI,
lowerHalf: false,
name: d.name
}
}
})
let textArc = d3.arc()
.outerRadius(outerRadius)
.innerRadius(outerRadius);
let textArcs = svg.selectAll('.text-arc').data(textArcData);
let textArcsEnter = textArcs.enter()
.append('path')
.attr('class', 'text-arc')
.merge(textArcs)
.attr('d', d => textArc(d))
.attr('id', (d, i) => 'textarc' + i)
.style("fill", "none");
svg.selectAll(".behaviorText")
.data(textArcData)
.enter().append("text")
.attr("class", "behaviorText")
.attr('dy', d => d.lowerHalf ? 14 : -4)
.append("textPath")
.attr("xlink:href", (d, i) => '#textarc' + i)
// since the arc wraps around, a quarter of the length will be the midpoint
.attr('startOffset', '25%')
.style("text-anchor","middle")
.text(d => d.name);
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment