Skip to content

Instantly share code, notes, and snippets.

@christophermanning
Last active March 30, 2023 04:24
  • Star 58 You must be signed in to star a gist
  • Fork 20 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save christophermanning/1734663 to your computer and use it in GitHub Desktop.
Voronoi Diagram with Force Directed Nodes and Delaunay Links
<!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.min.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: #EFEDF5;
fill: #EFEDF5;
}
line {
stroke: #EFEDF5;
pointer-events: none
}
path{
stroke: black
}
</style>
</head>
<body>
<div id="chart">
</div>
<script type="text/javascript">
var w = 960,
h = 500,
links = [],
voronoiVertices = [],
color = d3.scale.quantize().domain([7000, 10000]).range(d3.range(2, 9));
var vertices = d3.range(100).map(function(d) { return {x: d.x, y: d.y}; })
var zoomChargeScale = d3.scale.quantize().domain([0, 100]).range(d3.range(-10000, 1).reverse())
var zoom = d3.behavior.zoom()
.on("zoom", function(d,i) { force.charge(zoomChargeScale(d3.event.scale)).start() });
var svg = d3.select("#chart")
.append("svg")
.attr("width", w)
.attr("height", h)
.attr("class", "Purples")
.call(zoom)
var force = self.force = d3.layout.force()
.charge(-300)
.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 "q"+color(d3.geom.polygon(d).area())+"-9"; })
.attr("d", function(d) { return "M" + d.join("L") + "Z"; })
svg.selectAll("circle")
.data(vertices)
.enter().append("circle")
.call(force.drag)
.attr("r", 5)
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))
.attr("class", function(d, i) { return "q"+color(d3.geom.polygon(d).area())+"-9"; })
.attr("d", function(d) { return "M" + d.join("L") + "Z"; })
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>
@davefaliskie
Copy link

Is there a way to make each individual box a clickable link? Could you use JSON data to bind to each box? If so how?

@davefaliskie
Copy link

I did get the Voronoi to work with JSON data. I posted it at this link https://github.com/davefaliskie/voronoi_with_json I used Ruby on Rails, however the modified code from christophermanning can be found in assets -> javascripts -> d3_scripts.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment