|
<!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"> |
|
circle { |
|
stroke: #EFEDF5; |
|
fill: #EFEDF5; |
|
} |
|
line { |
|
pointer-events: none; |
|
stroke: #EFEDF5; |
|
stroke-width: 2px; |
|
opacity: .05; |
|
} |
|
path{ |
|
stroke: #EFEDF5; |
|
stroke-width: 4px; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div id="chart"> |
|
</div> |
|
<script type="text/javascript"> |
|
var w = 960, |
|
h = 500, |
|
links = [], |
|
// https://github.com/mbostock/d3/blob/master/lib/colorbrewer/colorbrewer.js#L105 |
|
color = d3.scale.quantize().domain([7000, 10000]).range(["#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"]) |
|
|
|
var numVertices = 150; |
|
var vertices = d3.range(numVertices).map(function(d) { return {x: d.x, y: d.y}; }); |
|
var d3_geom_voronoi = d3.geom.voronoi().x(function(d) { return d.x; }).y(function(d) { return 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 && d3.event.scale != prevEventScale) { |
|
vertices.pop(); |
|
} |
|
force.nodes(vertices).start() |
|
prevEventScale = d3.event.scale; |
|
}); |
|
|
|
var svg = d3.select("#chart") |
|
.append("svg") |
|
.attr("width", w) |
|
.attr("height", h) |
|
.call(zoom) |
|
|
|
var 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) { |
|
path = path.data(d3_geom_voronoi(vertices)) |
|
path.enter().insert("path", "path") //group all the path elements first so they have the lowest z-order |
|
.style("fill", function(d, i) { return color(0) }) |
|
path.attr("d", function(d) { return "M" + d.join("L") + "Z"; }) |
|
.transition().duration(150).style("fill", function(d, i) { return color(d3.geom.polygon(d).area()) }) |
|
path.exit().remove(); |
|
|
|
circle = circle.data(vertices) |
|
circle.enter().append("circle") |
|
.call(force.drag) |
|
.attr("r", 0) |
|
.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(); |
|
|
|
link = link.data(d3_geom_voronoi.links(vertices)) |
|
link.enter().append("line") |
|
link.attr("x1", function(d) { return d.source.x; }) |
|
.attr("y1", function(d) { return d.source.y; }) |
|
.attr("x2", function(d) { return d.target.x; }) |
|
.attr("y2", function(d) { return d.target.y; }) |
|
|
|
link.exit().remove() |
|
} |
|
</script> |
|
</body> |
|
</html> |