Is there an issue with correctly labelling d3
chord diagrams where the data contains zero values?
Consider this code for d3
version 7. I’m using the color names as data to make the point obvious.
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<script src="https://d3js.org/d3.v7.min.js"></script>
<link rel="stylesheet" type="text/css" href="css/style.css" />
<script>
function draw() {
// data, labels and colors.
let data = [
[0, 2, 3],
[4, 0, 6],
[7, 8, 0],
];
let labels = ["red", "green", "blue"];
let colors = ["red", "green", "blue"];
// plot dimensions
const width = 600;
const height = 600;
const margin = 120;
const radius = height / 2 - margin / 2;
// the `chord` object
const chord = d3.chord().padAngle(0.1);
const chords = chord(data);
// the ribbon object
const ribbon = d3.ribbon().radius(radius);
// The arc object
const arc = d3
.arc()
.innerRadius(radius + 2)
.outerRadius(radius + 30);
// the `color` function
const color = d3.scaleOrdinal().domain(labels).range(colors);
const svg = d3
.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
const plot = svg
.append("g")
.attr(
"transform",
`translate(${[width / 2 + margin / 4, height / 2 + margin / 4]})`,
);
// plotting the ribbons
const ribbons = plot
.selectAll("path.ribbon")
.data(chords)
.join("path")
.attr("class", "ribbon")
.attr("d", ribbon)
.style("opacity", 0.3)
.style("fill", (d) => color(d.source.index));
// plotting the arcs
plot.selectAll("path.arc")
.data(chords.groups)
.join("path")
.attr("class", "arc")
.attr("d", arc)
.style("fill", (d) => color(d.index));
// plotting the labels
plot.selectAll("text")
.data(chords.groups)
.join("text")
.attr("x", (d) => arc.centroid(d)[0])
.attr("y", (d) => arc.centroid(d)[1])
.attr("class", "label")
.style("fill", "white")
.text((d) => labels[d.index])
.attr(
"transform",
(d) =>
`rotate(${((arc.endAngle()(d) + arc.startAngle()(d)) *
90) /
Math.PI
}, ${arc.centroid(d)})`,
);
}
</script>
</head>
<body onload="draw()">
<div id="canvas"></div>
</body>
</html>
The initial zero knocks the labelling out of alignment. Is there any fix for this?
It’s possible to hack it by replacing the 0.01
, but that falls apart when the other numbers are quite small too. Also, it does feel a little too close to cheating.