Skip to content

Instantly share code, notes, and snippets.

@jezdi22j
Last active May 10, 2018 16:44
Show Gist options
  • Save jezdi22j/dbf1b091ea6a9dd1483fa7d814a463c4 to your computer and use it in GitHub Desktop.
Save jezdi22j/dbf1b091ea6a9dd1483fa7d814a463c4 to your computer and use it in GitHub Desktop.
voronoi energy use by water sector CA
license: lgpl-3.0

This block illustrates the use of the d3-voronoi-treemap plugin. This block is a remake of the HowMuch.net's article The Global Economy by GDP.

The d3-voronoi-treemap plugin produces Voronoï treemap. Given a convex polygon (here, a 60-gon simulating a circle for each gender) and nested weighted data, it tesselates/partitions the polygon in several inner cells which represent the hierarchical structure of your data, such that the area of a cell represents the weight of the underlying datum.

Acknowledgments to :

forked from Kcnarf's block: voronoi water use

{
"name": "world",
"children": [
{
"name": "Water End Uses",
"color": "#0B6EB6",
"children": [
{"name": "Industrial", "weight": 35, "code": "CN"},
{"name": "Agriculture", "weight": 2, "code": "JP"},
{"name": "Commercial", "weight": 9, "code": "IN"},
{
"name": "Residential",
"color": "#94BBD9",
"children": [
{"name": "Shower", "weight": 14, "code": "sh"},
{"name": "Faucet", "weight": 13, "code": "fc"},
{"name": "Clothes washer", "weight": 9, "code": "IN"},
{"name": "Bath", "weight": 2, "code": "fc"},
{"name": "Dishwasher", "weight": 3, "code": "IN"},
{"name": "Leaks", "weight": 1, "code": "IN"}
]
}
]
},
{
"name": "Water supply, conveyance, and treatment ",
"color": "#AE3B47",
"children": [
{"name": "Conveyance", "weight": 4, "code": "US"},
{"name": "Groundwater pumping", "weight": 3, "code": "CA"},
{"name": "Other supplies, treatment, and distribution", "weight": 3, "code": "MX"}
]
},
{
"name": "Wastewater treatment",
"color": "#D7A929",
"children": [
{"name": "Wastewater treatment", "weight": 2, "code": "RotW"}
]
}
]
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>d3-voronoi-treemap usage</title>
<meta name="description" content="d3-voronoi-treemap plugin to remake 'The Costs of Being Fat, in Actual Dollars'">
<script src="//d3js.org/d3.v4.min.js" charset="utf-8"></script>
<script src="https://raw.githack.com/Kcnarf/d3-weighted-voronoi/master/build/d3-weighted-voronoi.js"></script>
<script src="https://raw.githack.com/Kcnarf/d3-voronoi-map/master/build/d3-voronoi-map.js"></script>
<script src="https://raw.githack.com/Kcnarf/d3-voronoi-treemap/master/build/d3-voronoi-treemap.js"></script>
<style>
svg {
background-color: rgb(250,250,250);
}
#title {
letter-spacing: 4px;
font-weight: 700;
font-size: x-large;
}
text.tiny {
font-size: 10pt;
}
text.light {
fill: lightgrey
}
.world {
stroke: lightgrey;
stroke-width: 4px;
}
.cell {
stroke: white;
stroke-width: 1px;
}
.label {
text-anchor: middle;
fill: white;
}
.label>.name {
dominant-baseline: text-after-edge;
}
.label>.value {
dominant-baseline: text-before-edge;
}
.hoverer {
fill: transparent;
stroke: white;
stroke-width:0px;
}
.hoverer:hover {
stroke-width: 3px;
}
.legend-color {
stroke-width: 1px;
stroke:darkgrey;
}
</style>
</head>
<body>
<svg></svg>
<script>
//begin: constants
var _2PI = 2*Math.PI;
//end: constants
//begin: layout conf.
var svgWidth = 960,
svgHeight = 500,
margin = {top: 10, right: 10, bottom: 10, left: 10},
height = svgHeight - margin.top - margin.bottom,
width = svgWidth - margin.left - margin.right,
halfWidth = width/2,
halfHeight = height/2,
quarterWidth = width/4,
quarterHeight = height/4,
titleY = 20,
legendsMinY = height - 20,
treemapRadius = 205,
treemapCenter = [halfWidth, halfHeight+5];
//end: layout conf.
//begin: treemap conf.
var _voronoiTreemap = d3.voronoiTreemap();
var hierarchy, circlingPolygon;
//end: treemap conf.
//begin: drawing conf.
var fontScale = d3.scaleLinear();
//end: drawing conf.
//begin: reusable d3Selection
var svg, drawingArea, treemapContainer;
//end: reusable d3Selection
d3.json("globalEconomyByGDP.json", function(error, rootData) {
if (error) throw error;
initData();
initLayout(rootData);
hierarchy = d3.hierarchy(rootData).sum(function(d){ return d.weight; });
_voronoiTreemap
.clip(circlingPolygon)
(hierarchy);
drawTreemap(hierarchy);
});
function initData(rootData) {
circlingPolygon = computeCirclingPolygon(treemapRadius);
fontScale.domain([3, 20]).range([8, 20]).clamp(true);
}
function computeCirclingPolygon(radius) {
var points = 60,
increment = _2PI/points,
circlingPolygon = [];
for (var a=0, i=0; i<points; i++, a+=increment) {
circlingPolygon.push(
[radius + radius*Math.cos(a), radius + radius*Math.sin(a)]
)
}
return circlingPolygon;
};
function initLayout(rootData) {
svg = d3.select("svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
drawingArea = svg.append("g")
.classed("drawingArea", true)
.attr("transform", "translate("+[margin.left,margin.top]+")");
treemapContainer = drawingArea.append("g")
.classed("treemap-container", true)
.attr("transform", "translate("+treemapCenter+")");
treemapContainer.append("path")
.classed("world", true)
.attr("transform", "translate("+[-treemapRadius,-treemapRadius]+")")
.attr("d", "M"+circlingPolygon.join(",")+"Z");
drawTitle();
drawFooter();
drawLegends(rootData);
}
function drawTitle() {
drawingArea.append("text")
.attr("id", "title")
.attr("transform", "translate("+[halfWidth, titleY]+")")
.attr("text-anchor", "middle")
.text("Energy used by the water sector (175,950 GWh)")
}
function drawFooter() {
drawingArea.append("text")
.classed("tiny light", true)
.attr("transform", "translate("+[0, height]+")")
.attr("text-anchor", "start")
.text("Remake of HowMuch.net's article 'The Global Economy by GDP'")
drawingArea.append("text")
.classed("tiny light", true)
.attr("transform", "translate("+[halfWidth, height]+")")
.attr("text-anchor", "middle")
.text("by @_Kcnarf")
drawingArea.append("text")
.classed("tiny light", true)
.attr("transform", "translate("+[width, height]+")")
.attr("text-anchor", "end")
.text("bl.ocks.org/Kcnarf/fa95aa7b076f537c00aed614c29bb568")
}
function drawLegends(rootData) {
var legendHeight = 13,
interLegend = 4,
colorWidth = legendHeight*6,
continents = rootData.children.reverse();
var legendContainer = drawingArea.append("g")
.classed("legend", true)
.attr("transform", "translate("+[0, legendsMinY]+")");
var legends = legendContainer.selectAll(".legend")
.data(continents)
.enter();
var legend = legends.append("g")
.classed("legend", true)
.attr("transform", function(d,i){
return "translate("+[0, -i*(legendHeight+interLegend)]+")";
})
legend.append("rect")
.classed("legend-color", true)
.attr("y", -legendHeight)
.attr("width", colorWidth)
.attr("height", legendHeight)
.style("fill", function(d){ return d.color; });
legend.append("text")
.classed("tiny", true)
.attr("transform", "translate("+[colorWidth+5, -2]+")")
.text(function(d){ return d.name; });
legendContainer.append("text")
.attr("transform", "translate("+[0, -continents.length*(legendHeight+interLegend)-5]+")")
.text("Sector");
}
function drawTreemap(hierarchy) {
var leaves=hierarchy.leaves();
var cells = treemapContainer.append("g")
.classed('cells', true)
.attr("transform", "translate("+[-treemapRadius,-treemapRadius]+")")
.selectAll(".cell")
.data(leaves)
.enter()
.append("path")
.classed("cell", true)
.attr("d", function(d){ return "M"+d.polygon.join(",")+"z"; })
.style("fill", function(d){
return d.parent.data.color;
});
var labels = treemapContainer.append("g")
.classed('labels', true)
.attr("transform", "translate("+[-treemapRadius,-treemapRadius]+")")
.selectAll(".label")
.data(leaves)
.enter()
.append("g")
.classed("label", true)
.attr("transform", function(d){
return "translate("+[d.polygon.site.x, d.polygon.site.y]+")";
})
.style("font-size", function(d){ return fontScale(d.data.weight); });
labels.append("text")
.classed("name", true)
.html(function(d){
return (d.data.weight<1)? d.data.code : d.data.name;
});
labels.append("text")
.classed("value", true)
.text(function(d){ return d.data.weight+"%"; });
var hoverers = treemapContainer.append("g")
.classed('hoverers', true)
.attr("transform", "translate("+[-treemapRadius,-treemapRadius]+")")
.selectAll(".hoverer")
.data(leaves)
.enter()
.append("path")
.classed("hoverer", true)
.attr("d", function(d){ return "M"+d.polygon.join(",")+"z"; });
hoverers.append("title")
.text(function(d) { return d.data.name + "\n" + d.value+"%"; });
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment