Skip to content

Commit 7b1df15

Browse files
committed
Restructure force example.
1 parent 6363881 commit 7b1df15

5 files changed

Lines changed: 219 additions & 227 deletions

File tree

examples/force/cluster.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<title>Clustered Network</title>
55
<script type="text/javascript" src="../../d3.js"></script>
66
<script type="text/javascript" src="../../d3.geom.js"></script>
7-
<script type="text/javascript" src="force.js"></script>
7+
<script type="text/javascript" src="layout.js"></script>
88
<style type="text/css">
99
svg {
1010
border: 1px solid #ccc;

examples/force/force.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
circle.node {
2+
fill: lightsteelblue;
3+
stroke: steelblue;
4+
stroke-width: 1.5px;
5+
}
6+
7+
line.link {
8+
stroke: #333;
9+
}

examples/force/force.html

Lines changed: 4 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -3,76 +3,11 @@
33
<head>
44
<title>Force-Directed Layout</title>
55
<script type="text/javascript" src="../../d3.js"></script>
6-
<script type="text/javascript" src="force.js"></script>
7-
<style type="text/css">
8-
9-
body {
10-
font: 10px sans-serif;
11-
}
12-
13-
circle.node {
14-
fill: lightsteelblue;
15-
stroke: steelblue;
16-
stroke-width: 1.5px;
17-
}
18-
19-
line.link {
20-
stroke: #333;
21-
}
22-
23-
</style>
6+
<script type="text/javascript" src="layout.js"></script>
7+
<link type="text/css" rel="stylesheet" href="force.css"/>
248
</head>
259
<body>
26-
<script type="text/javascript">
27-
28-
var w = 960,
29-
h = 500;
30-
31-
var vis = d3.select("body")
32-
.append("svg:svg")
33-
.attr("width", w)
34-
.attr("height", h);
35-
36-
d3.json("miserables.json", function(json) {
37-
var force = layout_force()
38-
.nodes(json.nodes)
39-
.links(json.links)
40-
.size({x: w, y: h})
41-
.start();
42-
43-
var link = vis.selectAll("line.link")
44-
.data(json.links)
45-
.enter().append("svg:line")
46-
.attr("class", "link")
47-
.attr("x1", function(d) { return d.source.x; })
48-
.attr("y1", function(d) { return d.source.y; })
49-
.attr("x2", function(d) { return d.target.x; })
50-
.attr("y2", function(d) { return d.target.y; });
51-
52-
var node = vis.selectAll("circle.node")
53-
.data(json.nodes)
54-
.enter().append("svg:circle")
55-
.attr("class", "node")
56-
.attr("cx", function(d) { return d.x; })
57-
.attr("cy", function(d) { return d.y; })
58-
.attr("r", 4.5);
59-
60-
vis.attr("opacity", 0)
61-
.transition()
62-
.duration(1000)
63-
.attr("opacity", 1);
64-
65-
force.on("tick", function() {
66-
link.attr("x1", function(d) { return d.source.x; })
67-
.attr("y1", function(d) { return d.source.y; })
68-
.attr("x2", function(d) { return d.target.x; })
69-
.attr("y2", function(d) { return d.target.y; });
70-
71-
node.attr("cx", function(d) { return d.x; })
72-
.attr("cy", function(d) { return d.y; });
73-
});
74-
});
75-
76-
</script>
10+
<div id="chart"></div>
11+
<script type="text/javascript" src="force.js"></script>
7712
</body>
7813
</html>

examples/force/force.js

Lines changed: 47 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -1,157 +1,47 @@
1-
function layout_force() {
2-
var force = {},
3-
event = d3.dispatch("tick"),
4-
size = {x: 1, y: 1},
5-
alpha = .1,
6-
nodeDistance = 60,
7-
linkDistance = 30,
8-
interval,
9-
nodes,
10-
links;
11-
12-
// TODO
13-
// slow the interval as the graph stabilizes
14-
// allow the nodes to be dragged interactively
15-
16-
function tick() {
17-
var n = nodes.length,
18-
m = links.length,
19-
i, // current index
20-
j, // current index
21-
o, // current link
22-
s, // current source
23-
t, // current target
24-
l, // current distance
25-
x,
26-
y;
27-
28-
// repel nodes
29-
for (i = 0; i < n; ++i) {
30-
s = nodes[i];
31-
for (j = i + 1; j < n; ++j) {
32-
t = nodes[j];
33-
x = t.x - s.x;
34-
y = t.y - s.y;
35-
l = Math.sqrt(x * x + y * y);
36-
if (l < nodeDistance) {
37-
l = alpha * (l - nodeDistance) / l;
38-
x *= l;
39-
y *= l;
40-
if (s.fixed) {
41-
if (t.fixed) continue;
42-
t.x -= x;
43-
t.y -= y;
44-
} else if (t.fixed) {
45-
s.x += x;
46-
s.y += y;
47-
} else {
48-
s.x += x;
49-
s.y += y;
50-
t.x -= x;
51-
t.y -= y;
52-
}
53-
}
54-
}
55-
}
56-
57-
// position constraint for links
58-
for (i = 0; i < m; ++i) {
59-
o = links[i];
60-
s = o.source;
61-
t = o.target;
62-
x = t.x - s.x;
63-
y = t.y - s.y;
64-
l = Math.sqrt(x * x + y * y);
65-
if (l <= 0) l = 0.01;
66-
l = alpha * (l - linkDistance) / l;
67-
x *= l;
68-
y *= l;
69-
if (s.fixed) {
70-
if (t.fixed) continue;
71-
t.x -= x;
72-
t.y -= y;
73-
} else if (t.fixed) {
74-
s.x += x;
75-
s.y += y;
76-
} else {
77-
s.x += x;
78-
s.y += y;
79-
t.x -= x;
80-
t.y -= y;
81-
}
82-
}
83-
84-
event.tick.dispatch({type: "tick"});
85-
}
86-
87-
force.on = function(type, listener) {
88-
event[type].add(listener);
89-
return force;
90-
};
91-
92-
force.nodes = function(x) {
93-
if (!arguments.length) return nodes;
94-
nodes = x;
95-
return force;
96-
};
97-
98-
force.links = function(x) {
99-
if (!arguments.length) return links;
100-
links = x;
101-
return force;
102-
};
103-
104-
force.size = function(x) {
105-
if (!arguments.length) return size;
106-
size = x;
107-
return force;
108-
};
109-
110-
force.nodeDistance = function(d) {
111-
if (!arguments.length) return nodeDistance;
112-
nodeDistance = d;
113-
return force;
114-
};
115-
116-
force.linkDistance = function(d) {
117-
if (!arguments.length) return linkDistance;
118-
linkDistance = d;
119-
return force;
120-
};
121-
122-
force.start = function() {
123-
var i,
124-
n = nodes.length,
125-
m = links.length,
126-
w = size.x,
127-
h = size.y,
128-
o;
129-
for (i = 0; i < n; ++i) {
130-
o = nodes[i];
131-
o.x = o.x || Math.random() * w;
132-
o.y = o.y || Math.random() * h;
133-
o.fixed = 0;
134-
}
135-
for (i = 0; i < m; ++i) {
136-
o = links[i];
137-
o.source = nodes[o.source];
138-
o.target = nodes[o.target];
139-
}
140-
if (interval) clearInterval(interval);
141-
interval = setInterval(tick, 24);
142-
return force;
143-
};
144-
145-
force.resume = function() {
146-
if (interval) clearInterval(interval);
147-
interval = setInterval(tick, 24);
148-
return force;
149-
};
150-
151-
force.stop = function() {
152-
interval = clearInterval(interval);
153-
return force;
154-
};
155-
156-
return force;
157-
}
1+
var w = 960,
2+
h = 500;
3+
4+
var vis = d3.select("#chart")
5+
.append("svg:svg")
6+
.attr("width", w)
7+
.attr("height", h);
8+
9+
d3.json("miserables.json", function(json) {
10+
var force = layout_force()
11+
.nodes(json.nodes)
12+
.links(json.links)
13+
.size({x: w, y: h})
14+
.start();
15+
16+
var link = vis.selectAll("line.link")
17+
.data(json.links)
18+
.enter().append("svg:line")
19+
.attr("class", "link")
20+
.attr("x1", function(d) { return d.source.x; })
21+
.attr("y1", function(d) { return d.source.y; })
22+
.attr("x2", function(d) { return d.target.x; })
23+
.attr("y2", function(d) { return d.target.y; });
24+
25+
var node = vis.selectAll("circle.node")
26+
.data(json.nodes)
27+
.enter().append("svg:circle")
28+
.attr("class", "node")
29+
.attr("cx", function(d) { return d.x; })
30+
.attr("cy", function(d) { return d.y; })
31+
.attr("r", 4.5);
32+
33+
vis.attr("opacity", 0)
34+
.transition()
35+
.duration(1000)
36+
.attr("opacity", 1);
37+
38+
force.on("tick", function() {
39+
link.attr("x1", function(d) { return d.source.x; })
40+
.attr("y1", function(d) { return d.source.y; })
41+
.attr("x2", function(d) { return d.target.x; })
42+
.attr("y2", function(d) { return d.target.y; });
43+
44+
node.attr("cx", function(d) { return d.x; })
45+
.attr("cy", function(d) { return d.y; });
46+
});
47+
});

0 commit comments

Comments
 (0)