D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
emeeks
Full window
Github gist
Constrained Voronoi with Derived Areas
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> <script type="text/javascript" src="https://d3js.org/d3.v2.min.js"></script> <style type="text/css"> circle { stroke: #EFEDF5; fill: #EFEDF5; } line { stroke: #EFEDF5; pointer-events: none } path{ stroke: black } </style> </head> <body> <select id="colorSelect" onchange="setColor('menu')"> <option value="density">Density</option> <option value="equity">Equity</option> <option value="area">Area</option> <option value="statecode">State</option> <option value="green">Green</option> <option value="unpaved">Unpaved</option> </select> <div id="chart"> </div> <script type="text/javascript"> statesKey = {"AZ": 9,"CA": 9,"CO": 8,"DC": 3,"FL": 4,"GA": 4,"IL": 5,"MA": 1,"MI": 5,"NC": 4,"NM": 6,"NV": 9,"NY": 2,"OH": 5,"OR": 10,"PA": 3,"TN": 4,"TX": 6,"VA": 3,"WA": 10,"WI": 5}; w = 960, h = 960, links = [], voronoiVertices = [], color = d3.scale.quantize().domain([7000, 10000]).range(d3.range(2, 9)); var numVertices = 50; // vertices = d3.range(numVertices).map(function(d) { return {x: d.x, y: d.y}; }) d3.json("neighborhoods.json", function(json) { /* vertices = [{x: 0, y: 1, narea: 10}, {x: 100, y: 100, narea: 10}, {x: 0, y: 100, narea: 100}, {x: 100, y: 0, narea: 500}, {x: 0, y: 1, narea: 500}, {x: 100, y: 100, narea: 10}, {x: 0, y: 100, narea: 10}, {x: 100, y: 0, narea: 10}, {x: 0, y: 1, narea: 10}, {x: 100, y: 100, narea: 10}, {x: 0, y: 100, narea: 100}, {x: 100, y: 0, narea: 500}, {x: 0, y: 1, narea: 500}, {x: 100, y: 100, narea: 10}, {x: 0, y: 100, narea: 10}, {x: 100, y: 0, narea: 10}, {x: 0, y: 1, narea: 10}, {x: 100, y: 100, narea: 10}, {x: 0, y: 100, narea: 100}, {x: 100, y: 0, narea: 500}, {x: 0, y: 1, narea: 500}, {x: 100, y: 100, narea: 10}, {x: 0, y: 100, narea: 10}, {x: 100, y: 0, narea: 10} ] */ vertices = json; sizeMin = d3.min(vertices, function (d) { return d["area"];}); sizeMax = d3.max(vertices, function (d) { return d["area"];}); sizeMed = (sizeMin + sizeMax ) / 2; var prevEventScale = 1; xMin = d3.min(vertices, function (d) { return d["x"];}); xMax = d3.max(vertices, function (d) { return d["x"];}); yMin = d3.min(vertices, function (d) { return d["y"];}); yMax = d3.max(vertices, function (d) { return d["y"];}); sizeRamp = d3.scale.linear().domain([sizeMin,sizeMed,sizeMax]).range([-50,-250,-1000]); xRamp = d3.scale.linear().domain([xMin,xMax]).range([225,700]).clamp(true) yRamp = d3.scale.linear().domain([yMin,yMax]).range([700,225]).clamp(true) for ( n in vertices) { vertices[n]["x"] = xRamp(vertices[n]["x"]); vertices[n]["y"] = yRamp(vertices[n]["y"]); vertices[n]["statecode"] = statesKey[vertices[n]["state"]]; } /* 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) circleClip = svg.append("svg:clipPath").attr("id", "clipper").append("circle").attr("cx", w / 2).attr("cy", h / 2).attr("r", 325); force = self.force = d3.layout.force() .charge(function (d, i) { return sizeRamp(vertices[i].area)}) .size([w, h]) .on("tick", update); force.nodes(vertices).start(); circle = svg.selectAll("g.nodes"); path = svg.selectAll("path"); 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().append("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"; }) .attr("clip-path", "url(#clipper)") .style("stroke", "white") .style("stroke-width", 3) 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"; }) .attr("clip-path", "url(#clipper)") path.exit().remove(); circle = circle.data(vertices) circleEnter = circle.enter().append("g") .call(force.drag) .attr("class", "nodes") .attr("r", 0) .attr("transform", function (d) { return "translate("+d.x+","+d.y+")"}); // .attr("cy", function(d) { return d.y; }) circleEnter.append("circle") .transition().duration(1000).attr("r", 5); text1 = circleEnter.append("text") .attr("opacity", 0) .style("fill", "white") .style("stroke", "white") .style("stroke-width", "3") .text(function (d,i) {return vertices[i].name}) .transition().duration(1000).attr("opacity", .75); text2 = circleEnter.append("text") .attr("opacity", 0) .style("fill", "black") .text(function (d,i) {return vertices[i].name}) .transition().duration(1000).attr("opacity", 1); circle.attr("transform", function (d) { return "translate("+d.x+","+d.y+")"}); circle.exit().transition().attr("opacity", 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; }) .style("stroke", "none") link.exit().remove() circleClip.attr("r", function() { return d3.max(vertices, function (d) { return d["x"] - (w / 2) + (w / 20);}) } ); } function edge(a, b) { return { source: a, target: b }; } function setColor(inputString) { if (inputString == "menu") { inputString = document.getElementById("colorSelect").value; } colorMin = d3.min(vertices, function (d) { return d[inputString];}); colorMax = d3.max(vertices, function (d) { return d[inputString];}); colorMed = (colorMin + colorMax ) / 2; // colorRamp = d3.scale.linear().domain([colorMin,colorMed,colorMax]).range(["blue","yellow","red"]); colorRamp = d3.scale.linear().domain([1,100,400]).range(["green","yellow","purple"]); path.style("fill", function(d, i) { return colorRamp(vertices[i][inputString])}) text1.text(function (d,i) {return vertices[i][inputString]}) text2.text(function (d,i) {return vertices[i][inputString]}) } </script> </body> </html>
Modified
http://d3js.org/d3.v2.min.js
to a secure url
https://d3js.org/d3.v2.min.js