d3 chord diagram that produces parallel ribbons

1.4k views Asked by At

I currently am working with a chord layout, I would like to have my chords parallel though (illustrated with red overlays).

How do I accomplish this? I tried the different sorting options and none seem to yield the desired results.

enter image description here

code:

var width = 1000;
var height = 600;

var svg = d3.select("#chart")
        .append("svg")
        .attr("width", width)
        .attr("height", height)
        .append("g")
        .attr("transform", "translate(" + width/2 + "," + height/2 + ")");

var matrix5x5 = [
    [0, 1, 1, 1, 1, 1, 1, 1],
    [1, 0, 0, 0, 0, 0, 0, 0],
    [1, 0, 0, 0, 0, 0, 0, 0],
    [1, 0, 0, 0, 0, 0, 0, 0],
    [1, 0, 0, 0, 0, 0, 0, 0],
    [1, 0, 0, 0, 0, 0, 0, 0],   
    [1, 0, 0, 0, 0, 0, 0, 0],   
    [1, 0, 0, 0, 0, 0, 0, 0]            
];
var range5 = ["#848484", "#848484", "#848484", "#848484", "#848484", "#848484", "848484", "848484"];

var chord = d3.layout.chord()
        .padding(0.1)
        .matrix(matrix5x5);

var fill = d3.scale.ordinal()
        .domain(d3.range(range5.length))
        .range(range5);


var innerRadius = Math.min(width, height) * .39;
var outerRadius = innerRadius * 1.1;

svg.append("g")
        .selectAll("path")
        .data(chord.groups)
        .enter().append("path")
        .style("fill", function(d) {
            return fill(d.index);
        })
        .style("stroke", function(d) {
            return fill(d.index);
        })
        .attr("d", d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius))
        .on("mouseover", fade(.1))
        .on("mouseout", fade(1));

svg.append("g")
        .attr("class", "chord")
        .selectAll("path")
        .data(chord.chords)
        .enter().append("path")
        .style("fill", function(d) {
            return fill(d.target.index);
        })
        .attr("d", d3.svg.chord().radius(innerRadius))
        .style("opacity", 1);

var range5_artists = ["All", "one", "two", "three", "four", "five", "six", "seven"];

svg.selectAll("text")
        .data(chord.groups)
        .enter()
        .append("text")
        .text(function(d) {
            return range5_artists[d.index];
        })
      .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 + 35) + ")"
            + (d.angle > Math.PI ? "rotate(180)" : "");
      })
.style("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; })
        .attr("font-size", "11px")
        .attr("fill", function(d) {
            return  range5[d.index];
        })
        .on("mouseover", fade(.1))
        .on("mouseout", fade(1));


function fade(opacity) {
    return function(g, i) {
        svg.selectAll("g.chord path")
                .filter(function(d) {
                    return d.source.index != i && d.target.index != i;
                })
                .transition()
                .style("opacity", opacity);
    };
}
1

There are 1 answers

2
Lars Kotthoff On BEST ANSWER

What you're looking for here is the .sortSubGroups() function. You want to sort based on index, but this information isn't passed to the comparator. So we use a dirty trick that relies on the order of evaluation and always return 1.

Result here.