|
1 var w = 960, |
|
2 h = 500, |
|
3 mouse = [null, null], |
|
4 fill = d3.scale.linear().domain([0, 1e4]).range(["brown", "steelblue"]); |
|
5 |
|
6 // Initialise boids. |
|
7 var boids = d3.range(100).map(function() { |
|
8 return boid() |
|
9 .position([Math.random() * w, Math.random() * h]) |
|
10 .velocity([Math.random() * 2 - 1, Math.random() * 2 - 1]) |
|
11 .gravityCenter(mouse); |
|
12 }); |
|
13 |
|
14 // Compute initial positions. |
|
15 var vertices = boids.map(function(boid) { |
|
16 return boid(boids); |
|
17 }); |
|
18 |
|
19 d3.select(window).on("blur", nullGravity); |
|
20 |
|
21 var svg = d3.select("#vis") |
|
22 .append("svg:svg") |
|
23 .attr("width", w) |
|
24 .attr("height", h) |
|
25 .attr("class", "PiYG") |
|
26 .on("mousemove", function() { |
|
27 var m = d3.svg.mouse(this); |
|
28 mouse[0] = m[0]; |
|
29 mouse[1] = m[1]; |
|
30 }) |
|
31 .on("mouseout", nullGravity); |
|
32 |
|
33 svg.selectAll("path") |
|
34 .data(d3.geom.voronoi(vertices)) |
|
35 .enter().append("svg:path") |
|
36 .attr("class", function(d, i) { return i ? "q" + (i % 9) + "-9" : null; }) |
|
37 .attr("d", function(d) { return "M" + d.join("L") + "Z"; }); |
|
38 |
|
39 svg.selectAll("circle") |
|
40 .data(vertices) |
|
41 .enter().append("svg:circle") |
|
42 .attr("transform", function(d) { return "translate(" + d + ")"; }) |
|
43 .attr("r", 2); |
|
44 |
|
45 d3.timer(function() { |
|
46 // Update boid positions. |
|
47 boids.forEach(function(boid, i) { |
|
48 vertices[i] = boid(boids); |
|
49 }); |
|
50 |
|
51 // Update circle positions. |
|
52 svg.selectAll("circle") |
|
53 .data(vertices) |
|
54 .attr("transform", function(d) { return "translate(" + d + ")"; }); |
|
55 |
|
56 // Update voronoi diagram. |
|
57 svg.selectAll("path") |
|
58 .data(d3.geom.voronoi(vertices)) |
|
59 .attr("d", function(d) { return "M" + d.join("L") + "Z"; }) |
|
60 .style("fill", function(d) { return fill((d3.geom.polygon(d).area())); }); |
|
61 }); |
|
62 |
|
63 function nullGravity() { |
|
64 mouse[0] = mouse[1] = null; |
|
65 } |