A chord diagram in D3.js, showing dependencies between classes in a software class hierarchy. Dependencies are grouped according to the source and target packages. Although this diagram does not show class-level detail visible with hierarchical edge bundling, it better reveals the total number of imports between and within packages. Note, for example, the circular dependency between vis.data and vis.events. Colors by ColorBrewer.
See also this approach applied to Uber’s San Francisco cab data.
forked from mbostock's block: Chord Diagram
xxxxxxxxxx
<meta charset="utf-8">
<style>
</style>
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>
var outerRadius = 407,
width = 900,
height = 400,
innerRadius = outerRadius /2;
var chord = d3.chord()
.padAngle(0.05)
.sortSubgroups(d3.descending);
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var ribbon = d3.ribbon()
.radius(innerRadius);
var color = d3.scaleOrdinal(d3.schemeCategory20);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
d3.json("data.json", function(error, imports) {
if (error) throw error;
var indexByName = d3.map(),
nameByIndex = d3.map(),
matrix = [],
n = 0;
// Compute a unique index for each package name.
imports.forEach(function(d) {
if (!indexByName.has(d = d.name)) {
nameByIndex.set(n, d);
indexByName.set(d, n++);
}
});
// Construct a square matrix counting package imports.
imports.forEach(function(d) {
var source = indexByName.get(d.name),
row = matrix[source];
if (!row) {
row = matrix[source] = [];
for (var i =0; i < n;i++) row[i] = 0;
}
d.process.forEach(function(d) { row[indexByName.get(d)]++; });
console.log(row);
});
var g = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
.datum(chord(matrix));
var group = g.append("g")
.attr("class", "groups")
.selectAll("g")
.data(function(chords) { return chords.groups; })
.enter().append("g");
group.append("path")
.style("fill", function(d) { return color(d.index); })
.style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); })
.attr("d",arc);
group.append("text")
.each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; })
.attr("dy", ".35em")
.attr("transform", function(d) {
return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")"
+ "translate(" + (innerRadius + 26) + ")"
+ (d.angle > Math.PI ? "rotate(180)" : "");
})
.style("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; })
.text(function(d) { return nameByIndex.get(d.index); });
g.append("g")
.attr("class", "ribbons")
.selectAll("path")
.data(function(chords) { return chords; })
.enter().append("path")
.attr("d", ribbon)
.style("fill", function(d) { return color(d.target.index); })
.style("stroke", function(d) { return d3.rgb(color(d.source.index)); })
.style("stroke-width", "3px");
});
</script>
https://d3js.org/d3.v4.min.js