<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> <script type="text/javascript" src="http://mbostock.github.com/d3/d3.min.js"></script> <script type="text/javascript" src="http://mbostock.github.com/d3/d3.geom.js"></script> <script type="text/javascript" src="http://mbostock.github.com/d3/d3.layout.min.js"></script> <link rel="stylesheet" href="http://mbostock.github.com/d3/ex/colorbrewer.css"> <style type="text/css"> circle { stroke: black; stroke-opacity: .5; fill: white; } line { stroke: #999; pointer-events: none } path{ fill:white; stroke: black } </style> </head> <body> <div id="chart"> </div> <script type="text/javascript"> var w = 960, h = 500, links = [], voronoiVertices = []; var vertices = d3.range(100).map(function(d) { lx = Math.random() * w ly = Math.random() * h return {x: lx, y: ly, index: parseInt(lx + ly)}; }) var svg = d3.select("#chart") .append("svg") .attr("width", w) .attr("height", h) .attr("class", "Purples") var force = self.force = d3.layout.force() .gravity(.01) .size([w, h]) .on("tick", update); force.nodes(vertices).start(); svg.selectAll("path") .data(d3.geom.voronoi(vertices.map(function(o){return [o.x, o.y]}))) .enter().append("path") .attr("class", function(d, i) { return i ? "q" + (i % 9) + "-9" : null; }) .attr("d", function(d) { return "M" + d.join("L") + "Z"; }); svg.selectAll("circle") .data(vertices) .enter().append("circle") .call(force.drag) .attr("r", 10); var link = svg.selectAll("line") function update(e) { voronoiVertices = vertices.map(function(o){return [o.x, o.y, o]}) svg.selectAll("circle") .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); svg.selectAll("path") .data(d3.geom.voronoi(voronoiVertices)) .map(function(d) { return "M" + d.join("L") + "Z"; }) .filter(function(d) { return this.getAttribute("d") != d; }) .attr("d", function(d) { return d; }); links = [] d3.geom.delaunay(voronoiVertices).forEach(function(d) { links.push(edge(d[0], d[1])); links.push(edge(d[1], d[2])); links.push(edge(d[2], d[0])); }); link = link.data(links) link.enter().append("line") link.attr("x1", function(d) { return d.source[2].x; }) .attr("y1", function(d) { return d.source[2].y; }) .attr("x2", function(d) { return d.target[2].x; }) .attr("y2", function(d) { return d.target[2].y; }) link.exit().remove() } function edge(a, b) { return { source: a, target: b }; } </script> </body> </html>