diagnostics: added chord viewer
Juan Batiz-Benet committed
Jan 14, 2015 at 09:18 UTC
b9f828e1e3e04ca9f4bb8f38a6be1e66d40b43d9
1 file changed
+166
diagnostics/d3/chord.html
new
+166
@@ -0,0 +1,166 @@
1
+<!DOCTYPE html>
2
+<meta charset="utf-8">
3
+<style>
4
+
5
+.node {
6
+ font: 11px "Helvetica Neue", Helvetica, Arial, sans-serif;
7
+}
8
+
9
+.link {
10
+ stroke: steelblue;
11
+ stroke-opacity: .4;
12
+ fill: none;
13
+}
14
+
15
+</style>
16
+<body>
17
+<script src="http://d3js.org/d3.v3.min.js"></script>
18
+<script>
19
+var hash = window.location.hash.substring(1)
20
+
21
+var diameter = 1400,
22
+ radius = diameter / 2,
23
+ innerRadius = radius - 200
24
+ rotate = 145;
25
+
26
+var color = d3.scale.category10()
27
+
28
+var diagonal = d3.svg.diagonal.radial()
29
+ .projection(function(d) { return [d.y, d.x / 180 * Math.PI]; });
30
+
31
+var svg = d3.select("body").append("svg")
32
+ .attr("width", "100%")
33
+ .attr("height", "100%")
34
+ .attr("viewBox", "0 0 " + diameter + " " + diameter )
35
+ .attr("preserveAspectRatio", "xMidYMid meet")
36
+ .append("g")
37
+ .attr("transform", "translate(" + radius + "," + radius + ")");
38
+
39
+d3.json(hash, function(error, data) {
40
+
41
+ graph = parseGraph(data)
42
+
43
+ var node = svg.selectAll(".node")
44
+ .data(graph.nodes)
45
+ .enter().append("g")
46
+ .attr("class", "node")
47
+ .attr("transform", function(d) { return "rotate(" + (d.x - 90 + rotate) + ")translate(" + d.y + ")"; })
48
+
49
+ node.append("svg:circle")
50
+ .attr("r", function(d) { return 4; })
51
+ .style("fill", function(d, i) { return color(i % 3); })
52
+
53
+ node.append("text")
54
+ .attr("dx", function(d) { return 8; })
55
+ .attr("dy", ".31em")
56
+ // .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
57
+ // .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; })
58
+ .text(function(d) { return truncate(d.name, 16); });
59
+
60
+ var p = projection
61
+ var link = svg.selectAll(".link")
62
+ .data(graph.paths)
63
+ .enter().append("path")
64
+ .attr("class", "link")
65
+ .attr("d", function(d) {
66
+ return "M" + p(d[0])[0] + "," + p(d[0])[1]
67
+ + "S" + p(d[1])[0] + "," + p(d[1])[1]
68
+ + " " + p(d[2])[0] + "," + p(d[2])[1];
69
+ })
70
+
71
+ // var mid = svg.selectAll(".node-mid")
72
+ // .data(graph.mids)
73
+ // .enter().append("g")
74
+ // .attr("class", "node-mid")
75
+ // .attr("transform", function(d) { return "rotate(" + (d.x + rotate) + ")translate(" + d.y + ")"; })
76
+
77
+ // mid.append("svg:circle")
78
+ // .attr("r", function(d) { return 4; })
79
+ // .style("fill", function(d, i) { return color(i % 3); })
80
+
81
+ console.log(graph.paths)
82
+});
83
+
84
+
85
+function parseGraph(graph2) {
86
+ graph = {}
87
+ graph.nodes = []
88
+ graph.links = []
89
+ graph.paths = []
90
+ graph.byName = {}
91
+ graph.mids = []
92
+
93
+ graph2.nodes.sort(function(a, b) {
94
+ if (a.name > b.name) return 1;
95
+ if (a.name < b.name) return -1;
96
+ return 0;
97
+ })
98
+
99
+ graph2.nodes.forEach(function(data, i) {
100
+ data.y = innerRadius
101
+ data.x = ((360 / graph2.nodes.length) * i)
102
+ graph.nodes.push(data)
103
+ graph.byName[data.name] = data
104
+ })
105
+
106
+ graph2.links.forEach(function(link) {
107
+ var source = graph2.nodes[link.source]
108
+ var target = graph2.nodes[link.target]
109
+
110
+ var mid = curveNode(source, target)
111
+ graph.mids.push(mid)
112
+
113
+ var link1 = {source: source, target: mid, value: link.value || 3}
114
+ var link2 = {source: mid, target: target, value: link.value || 3}
115
+ graph.links.push(link1)
116
+ graph.links.push(link2)
117
+
118
+ var path = [source, mid, target]
119
+ graph.paths.push(path)
120
+ })
121
+
122
+ return graph
123
+}
124
+
125
+function curveNode(source, target) {
126
+ var d = circleDistance(source.x, target.x)
127
+ var h = ((1-(d/180)) * innerRadius) * 0.7
128
+ var x = circleMidpoint(source.x, target.x)
129
+ return {x: x, y: h}
130
+}
131
+
132
+function circleMidpoint(x, y) {
133
+ var x2 = x > y ? x : y
134
+ var y2 = x > y ? y : x
135
+ var a = (x2-y2)
136
+ if (a > 180) {
137
+ a = 360 - a
138
+ return (x2 + a/2) % 360
139
+ } else {
140
+ return (y2 + a/2) % 360
141
+ }
142
+}
143
+
144
+function circleDistance(x, y) {
145
+ var a = abs(x-y)
146
+ return (a > 180) ? 360 - a : a
147
+}
148
+
149
+function abs(x) {
150
+ return x < 0 ? -x : x
151
+}
152
+
153
+function projection(d) {
154
+ var r = d.y, a = (d.x - 90 + rotate) / 180 * Math.PI;
155
+ return [r * Math.cos(a), r * Math.sin(a)];
156
+}
157
+
158
+function truncate(name, limit) {
159
+ return name.substring(0, limit)
160
+}
161
+
162
+
163
+d3.select(self.frameElement).style("height", "100%");
164
+d3.select(self.frameElement).style("width", "100%");
165
+
166
+</script>