Created by Christopher Manning
Nodes are linked to nodes in neighboring cells. The cell's color is a function of its area.
- Drag the nodes to interact with the diagram.
- Use the mousewheel to add/remove nodes.
Created by Christopher Manning
Nodes are linked to nodes in neighboring cells. The cell's color is a function of its area.
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<style type="text/css"> | |
.Purples .q0-3{fill:rgb(239,237,245)} | |
.Purples .q1-3{fill:rgb(188,189,220)} | |
.Purples .q2-3{fill:rgb(117,107,177)} | |
.Purples .q0-4{fill:rgb(242,240,247)} | |
.Purples .q1-4{fill:rgb(203,201,226)} | |
.Purples .q2-4{fill:rgb(158,154,200)} | |
.Purples .q3-4{fill:rgb(106,81,163)} | |
.Purples .q0-5{fill:rgb(242,240,247)} | |
.Purples .q1-5{fill:rgb(203,201,226)} | |
.Purples .q2-5{fill:rgb(158,154,200)} | |
.Purples .q3-5{fill:rgb(117,107,177)} | |
.Purples .q4-5{fill:rgb(84,39,143)} | |
.Purples .q0-6{fill:rgb(242,240,247)} | |
.Purples .q1-6{fill:rgb(218,218,235)} | |
.Purples .q2-6{fill:rgb(188,189,220)} | |
.Purples .q3-6{fill:rgb(158,154,200)} | |
.Purples .q4-6{fill:rgb(117,107,177)} | |
.Purples .q5-6{fill:rgb(84,39,143)} | |
.Purples .q0-7{fill:rgb(242,240,247)} | |
.Purples .q1-7{fill:rgb(218,218,235)} | |
.Purples .q2-7{fill:rgb(188,189,220)} | |
.Purples .q3-7{fill:rgb(158,154,200)} | |
.Purples .q4-7{fill:rgb(128,125,186)} | |
.Purples .q5-7{fill:rgb(106,81,163)} | |
.Purples .q6-7{fill:rgb(74,20,134)} | |
.Purples .q0-8{fill:rgb(252,251,253)} | |
.Purples .q1-8{fill:rgb(239,237,245)} | |
.Purples .q2-8{fill:rgb(218,218,235)} | |
.Purples .q3-8{fill:rgb(188,189,220)} | |
.Purples .q4-8{fill:rgb(158,154,200)} | |
.Purples .q5-8{fill:rgb(128,125,186)} | |
.Purples .q6-8{fill:rgb(106,81,163)} | |
.Purples .q7-8{fill:rgb(74,20,134)} | |
.Purples .q0-9{fill:rgb(252,251,253)} | |
.Purples .q1-9{fill:rgb(239,237,245)} | |
.Purples .q2-9{fill:rgb(218,218,235)} | |
.Purples .q3-9{fill:rgb(188,189,220)} | |
.Purples .q4-9{fill:rgb(158,154,200)} | |
.Purples .q5-9{fill:rgb(128,125,186)} | |
.Purples .q6-9{fill:rgb(106,81,163)} | |
.Purples .q7-9{fill:rgb(84,39,143)} | |
.Purples .q8-9{fill:rgb(63,0,125)} | |
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 numVertices = 150; | |
var vertices = d3.range(numVertices).map(function(d) { return {x: d.x, y: d.y}; }) | |
var prevEventScale = 1; | |
var zoom = d3.behavior.zoom().on("zoom", function(d,i) { | |
if (d3.event.scale > prevEventScale) { | |
vertices.push(function(d) { return {x: d.x, y: d.y}; }) | |
} else if (vertices.length > 2) { | |
vertices.pop(); | |
} | |
force.nodes(vertices).start() | |
prevEventScale = d3.event.scale; | |
}); | |
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(); | |
var circle = svg.selectAll("circle"); | |
var path = svg.selectAll("path"); | |
var link = svg.selectAll("line"); | |
function update(e) { | |
voronoiVertices = vertices.map(function(o){return [o.x, o.y, o]}) | |
path = path.data(d3.geom.voronoi(voronoiVertices)) | |
path.enter().insert("path", "path") //group all the path elements first so they have the lowest z-order | |
.attr("class", function(d, i) { return "q"+color(d3.geom.polygon(d).area())+"-9"; }) | |
.attr("d", function(d) { return "M" + d.join("L") + "Z"; }); | |
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"; }); | |
path.exit().remove(); | |
circle = circle.data(vertices) | |
circle.enter().append("circle") | |
.call(force.drag) | |
.attr("r", 0) | |
.attr("cx", function(d) { return d.x; }) | |
.attr("cy", function(d) { return d.y; }) | |
.transition().duration(1000).attr("r", 5); | |
circle.attr("cx", function(d) { return d.x; }) | |
.attr("cy", function(d) { return d.y; }); | |
circle.exit().transition().attr("r", 0).remove(); | |
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> |
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
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?