| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 |
|
| 19 | var outerRadius = Math.max(nodeArray.length * 15, 500) / 2,
|
| 20 | innerRadius = outerRadius - Math.min(nodeArray.length * 5, 200),
|
| 21 | width = outerRadius * 2,
|
| 22 | height = outerRadius * 2,
|
| 23 | colors = d3.scale.category20c(),
|
| 24 | matrix = [];
|
| 25 |
|
| 26 | function neighborsOf (node) {
|
| 27 | return links.filter(function (e) {
|
| 28 | return e.source === node;
|
| 29 | }).map(function (e) {
|
| 30 | return e.target;
|
| 31 | });
|
| 32 | }
|
| 33 |
|
| 34 | function zoomed () {
|
| 35 | zoomer.attr("transform",
|
| 36 | "translate(" + d3.event.translate + ")" +
|
| 37 | "scale(" + d3.event.scale + ")");
|
| 38 | }
|
| 39 |
|
| 40 | function fade (opacity, root) {
|
| 41 | return function (g, i) {
|
| 42 | root.selectAll("g path.chord")
|
| 43 | .filter(function (d) {
|
| 44 | return d.source.index != i && d.target.index != i;
|
| 45 | })
|
| 46 | .transition()
|
| 47 | .style("opacity", opacity);
|
| 48 | };
|
| 49 | }
|
| 50 |
|
| 51 | |
| 52 | |
| 53 | links.forEach(function (link) {
|
| 54 | link.target = nodes[link.target];
|
| 55 | link.source = nodes[link.source];
|
| 56 | });
|
| 57 |
|
| 58 | |
| 59 | nodeArray.forEach(function (d, index, arr) {
|
| 60 | var source = index,
|
| 61 | row = matrix[source];
|
| 62 | if (!row) {
|
| 63 | row = matrix[source] = [];
|
| 64 | for (var i = -1; ++i < arr.length;) row[i] = 0;
|
| 65 | }
|
| 66 | neighborsOf(d).forEach(function (d) { row[d.index]++; });
|
| 67 | });
|
| 68 |
|
| 69 | |
| 70 | var chord = d3.layout.chord()
|
| 71 | .padding(0.01)
|
| 72 | .sortSubgroups(d3.descending)
|
| 73 | .sortChords(d3.descending)
|
| 74 | .matrix(matrix);
|
| 75 |
|
| 76 | var arc = d3.svg.arc()
|
| 77 | .innerRadius(innerRadius)
|
| 78 | .outerRadius(innerRadius + 20);
|
| 79 |
|
| 80 | var zoom = d3.behavior.zoom()
|
| 81 | .scaleExtent([0.1, 10])
|
| 82 | .on("zoom", zoomed);
|
| 83 |
|
| 84 | var svg = d3.select("body").append("svg")
|
| 85 | .attr("width", "100%")
|
| 86 | .attr("height", "100%")
|
| 87 | .attr('viewBox', '0 0 ' + Math.min(width, height) + ' ' + Math.min(width, height))
|
| 88 | .attr('preserveAspectRatio', 'xMinYMin')
|
| 89 | .call(zoom);
|
| 90 |
|
| 91 | var zoomer = svg.append("g");
|
| 92 |
|
| 93 | var container = zoomer.append("g")
|
| 94 | .attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");
|
| 95 |
|
| 96 | |
| 97 | var g = container.selectAll(".group")
|
| 98 | .data(chord.groups)
|
| 99 | .enter().append("g")
|
| 100 | .attr("class", "group")
|
| 101 | .on("mouseout", fade(1, container))
|
| 102 | .on("mouseover", fade(0.1, container));
|
| 103 |
|
| 104 | |
| 105 | g.append("path")
|
| 106 | .style("fill", function (d) { return colors(d.index); })
|
| 107 | .style("stroke", function (d) { return colors(d.index); })
|
| 108 | .attr("d", arc);
|
| 109 |
|
| 110 | |
| 111 | g.append("text")
|
| 112 | .each(function (d) { d.angle = (d.startAngle + d.endAngle) / 2; })
|
| 113 | .attr("dy", ".35em")
|
| 114 | .attr("transform", function (d) {
|
| 115 | return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")"
|
| 116 | + "translate(" + (innerRadius + 26) + ")"
|
| 117 | + (d.angle > Math.PI ? "rotate(180)" : "");
|
| 118 | })
|
| 119 | .style("text-anchor", function (d) { return d.angle > Math.PI ? "end" : null; })
|
| 120 | .text(function (d) { return nodeArray[d.index].label; });
|
| 121 |
|
| 122 | |
| 123 | container.selectAll(".chord")
|
| 124 | .data(chord.chords)
|
| 125 | .enter().append("path")
|
| 126 | .attr("class", "chord")
|
| 127 | .style("stroke", function (d) { return d3.rgb(colors(d.source.index)).darker(); })
|
| 128 | .style("fill", function (d) { return colors(d.source.index); })
|
| 129 | .attr("d", d3.svg.chord().radius(innerRadius));
|