Skip to content

Commit 80e0e78

Browse files
committed
Merge pull request d3#508 from jasondavies/rollup
Add PivotGraph (rollup) layout example.
2 parents 7a4a8ec + 58e640c commit 80e0e78

1 file changed

Lines changed: 236 additions & 0 deletions

File tree

examples/rollup/rollup.html

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
<!DOCTYPE html>
2+
<meta charset="utf-8">
3+
<title>PivotGraph (Rollup) Layout</title>
4+
5+
<style>
6+
body { font-family: sans-serif; font-size: 10px; }
7+
path { fill: none; stroke: #ccc; }
8+
circle { fill: #fff; stroke: steelblue; }
9+
</style>
10+
<script src="../../d3.js"></script>
11+
12+
<body>
13+
<script>
14+
var social = {
15+
nodes: [
16+
{gender: "M", group: 1},
17+
{gender: "F", group: 2},
18+
{gender: "M", group: 1},
19+
{gender: "M", group: 2},
20+
{gender: "F", group: 2},
21+
{gender: "M", group: 1},
22+
{gender: "F", group: 1},
23+
{gender: "M", group: 2},
24+
{gender: "F", group: 2},
25+
{gender: "F", group: 2}
26+
],
27+
links: [
28+
{source: 0, target: 1},
29+
{source: 1, target: 2},
30+
{source: 2, target: 3},
31+
{source: 2, target: 4},
32+
{source: 2, target: 5},
33+
{source: 2, target: 6},
34+
{source: 2, target: 7},
35+
{source: 5, target: 6},
36+
{source: 6, target: 7},
37+
{source: 5, target: 8},
38+
{source: 8, target: 6},
39+
{source: 6, target: 9}
40+
]
41+
};
42+
43+
var w = 100,
44+
h = 100,
45+
p = 30,
46+
x = d3.scale.ordinal().domain(social.nodes.map(fx)).range([0, w]),
47+
y = d3.scale.ordinal().domain(social.nodes.map(fy)).range([0, h]);
48+
49+
function fx(d) { return d.gender; }
50+
function fy(d) { return d.group; }
51+
52+
var vis = d3.select("body").append("svg")
53+
.attr("w", w + 2 * p)
54+
.attr("h", h + 2 * p)
55+
.append("g")
56+
.attr("transform", "translate(" + [p, p] + ")");
57+
58+
var layout = rollup()
59+
.x(function(d) { return x(fx(d)); })
60+
.y(function(d) { return y(fy(d)); });
61+
62+
var g = layout(social);
63+
64+
vis.selectAll("path")
65+
.data(g.links)
66+
.enter().append("path")
67+
.style("stroke-width", function(d) { return d.value * 1.5; })
68+
.attr("d", function(d) {
69+
var tx = d.target.x,
70+
sx = d.source.x,
71+
ty = d.target.y,
72+
sy = d.source.y,
73+
dx = tx - sx,
74+
dy = ty - sy,
75+
dr = 2 * Math.sqrt(dx * dx + dy * dy);
76+
return "M" + sx + "," + sy + "A" + dr + "," + dr + " 0 0,1 " + tx + "," + ty;
77+
});
78+
79+
vis.selectAll("circle")
80+
.data(g.nodes)
81+
.enter().append("circle")
82+
.attr("r", function(d) { return Math.sqrt(d.nodes.length * 20); })
83+
.attr("cx", function(d) { return d.x; })
84+
.attr("cy", function(d) { return d.y; });
85+
86+
vis.selectAll("text.x")
87+
.data(x.domain())
88+
.enter().append("text")
89+
.attr("class", "x")
90+
.attr("x", x)
91+
.attr("y", -10)
92+
.attr("text-anchor", "middle")
93+
.text(String);
94+
95+
vis.selectAll("text.y")
96+
.data(y.domain())
97+
.enter().append("text")
98+
.attr("class", "y")
99+
.attr("x", -10)
100+
.attr("dy", ".3em")
101+
.attr("y", y)
102+
.attr("text-anchor", "end")
103+
.text(String);
104+
105+
function rollup() {
106+
var directed = true,
107+
x_ = rollupX,
108+
y_ = rollupY,
109+
nodes_ = rollupNodes,
110+
links_ = rollupLinks,
111+
linkValue = rollupLinkValue,
112+
linkSource = rollupLinkSource,
113+
linkTarget = rollupLinkTarget;
114+
115+
function rollup(d, i) {
116+
var nodes = nodes_.call(this, d, i),
117+
links = links_.call(this, d, i),
118+
n = nodes.length,
119+
m = links.length,
120+
i = -1,
121+
x = [],
122+
y = [],
123+
rnindex = 0,
124+
rnodes = {},
125+
rlinks = {};
126+
127+
// Compute rollup nodes.
128+
while (++i < n) {
129+
(d = nodes[i]).index = i;
130+
x[i] = x_.call(this, d, i);
131+
y[i] = y_.call(this, d, i);
132+
var nodeId = id(i),
133+
rn = rnodes[nodeId];
134+
if (!rn) {
135+
rn = rnodes[nodeId] = {
136+
index: rnindex++,
137+
x: x[i],
138+
y: y[i],
139+
nodes: []
140+
};
141+
}
142+
rn.nodes.push(d);
143+
}
144+
145+
// Compute rollup links.
146+
i = -1; while (++i < m) {
147+
var value = linkValue.call(this, d = links[i], i),
148+
source = linkSource.call(this, d, i),
149+
target = linkTarget.call(this, d, i),
150+
rsource = rnodes[id(typeof source === "number" ? source : source.index)],
151+
rtarget = rnodes[id(typeof target === "number" ? target : target.index)],
152+
linkId = !directed && rsource.index > rtarget.index
153+
? rtarget.index + "," + rsource.index
154+
: rsource.index + "," + rtarget.index,
155+
rl = rlinks[linkId];
156+
if (!rl) {
157+
rl = rlinks[linkId] = {
158+
source: rsource,
159+
target: rtarget,
160+
value: 0,
161+
links: []
162+
};
163+
}
164+
rl.links.push(links[i]);
165+
rl.value += value;
166+
}
167+
168+
return {
169+
nodes: d3.values(rnodes),
170+
links: d3.values(rlinks)
171+
};
172+
173+
function id(i) {
174+
return x[i] + "," + y[i];
175+
}
176+
}
177+
178+
rollup.x = function(x) {
179+
if (!arguments.length) return x_;
180+
x_ = x;
181+
return rollup;
182+
};
183+
184+
rollup.y = function(x) {
185+
if (!arguments.length) return y_;
186+
y_ = x;
187+
return rollup;
188+
};
189+
190+
rollup.nodes = function(x) {
191+
if (!arguments.length) return nodes_;
192+
nodes_ = x;
193+
return rollup;
194+
};
195+
196+
rollup.links = function(x) {
197+
if (!arguments.length) return links_;
198+
links_ = x;
199+
return rollup;
200+
};
201+
202+
rollup.linkSource = function(x) {
203+
if (!arguments.length) return linkSource;
204+
linkSource = x;
205+
return rollup;
206+
};
207+
208+
rollup.linkTarget = function(x) {
209+
if (!arguments.length) return linkTarget;
210+
linkTarget = x;
211+
return rollup;
212+
};
213+
214+
rollup.linkValue = function(x) {
215+
if (!arguments.length) return linkValue;
216+
linkValue = x;
217+
return rollup;
218+
};
219+
220+
rollup.directed = function(x) {
221+
if (!arguments.length) return directed;
222+
directed = x;
223+
return rollup;
224+
};
225+
226+
return rollup;
227+
228+
function rollupX(d) { return d.x; }
229+
function rollupY(d) { return d.y; }
230+
function rollupNodes(d) { return d.nodes; }
231+
function rollupLinks(d) { return d.links; }
232+
function rollupLinkValue(d) { return 1; }
233+
function rollupLinkSource(d) { return d.source; }
234+
function rollupLinkTarget(d) { return d.target; }
235+
}
236+
</script>

0 commit comments

Comments
 (0)