gnu: easyrpg-player: Update to 0.6.2.2.
[jackhill/guix/guix.git] / graph.js
CommitLineData
4d93f312
RW
1// GNU Guix --- Functional package management for GNU
2// Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
3//
4// This file is part of GNU Guix.
5//
6// GNU Guix is free software; you can redistribute it and/or modify it
7// under the terms of the GNU General Public License as published by
8// the Free Software Foundation; either version 3 of the License, or (at
9// your option) any later version.
10//
11// GNU Guix is distributed in the hope that it will be useful, but
12// WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19var 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
26function neighborsOf (node) {
27 return links.filter(function (e) {
28 return e.source === node;
29 }).map(function (e) {
30 return e.target;
31 });
32}
33
34function zoomed () {
35 zoomer.attr("transform",
36 "translate(" + d3.event.translate + ")" +
37 "scale(" + d3.event.scale + ")");
38}
39
40function 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// Now that we have all nodes in an object we can replace each reference
52// with the actual node object.
53links.forEach(function (link) {
54 link.target = nodes[link.target];
55 link.source = nodes[link.source];
56});
57
58// Construct a square matrix for package dependencies
59nodeArray.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// chord layout
70var chord = d3.layout.chord()
71 .padding(0.01)
72 .sortSubgroups(d3.descending)
73 .sortChords(d3.descending)
74 .matrix(matrix);
75
76var arc = d3.svg.arc()
77 .innerRadius(innerRadius)
78 .outerRadius(innerRadius + 20);
79
80var zoom = d3.behavior.zoom()
81 .scaleExtent([0.1, 10])
82 .on("zoom", zoomed);
83
84var 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
91var zoomer = svg.append("g");
92
93var container = zoomer.append("g")
94 .attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");
95
96// Group for arcs and labels
97var 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// Draw one segment per package
105g.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// Add circular labels
111g.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// Draw chords from source to target; color by source.
123container.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));