Skip to content

Instantly share code, notes, and snippets.



Last active Sep 29, 2020
What would you like to do?
d3-voronoi-treemap usage
license: lgpl-3.0

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

The d3-voronoi-treemap plugin produces Voronoï treemap. Given a convex polygon (here, a 60-gon representing our Earth) 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 :

"name": "world",
"children": [
"name": "Asia",
"color": "#f58321",
"children": [
{"name": "China", "weight": 14.84, "code": "CN"},
{"name": "Japan", "weight": 5.91, "code": "JP"},
{"name": "India", "weight": 2.83, "code": "IN"},
{"name": "South Korea", "weight": 1.86, "code": "KR"},
{"name": "Russia", "weight": 1.8, "code": "RU"},
{"name": "Indonesia", "weight": 1.16, "code": "ID"},
{"name": "Turkey", "weight": 0.97, "code": "TR"},
{"name": "Saudi Arabia", "weight": 0.87, "code": "SA"},
{"name": "Iran", "weight": 0.57, "code": "IR"},
{"name": "Thaïland", "weight": 0.53, "code": "TH"},
{"name": "United Arab Emirates", "weight": 0.5, "code": "AE"},
{"name": "Hong Kong", "weight": 0.42, "code": "HK"},
{"name": "Israel", "weight": 0.4, "code": "IL"},
{"name": "Malasya", "weight": 0.4, "code": "MY"},
{"name": "Singapore", "weight": 0.39, "code": "SG"},
{"name": "Philippines", "weight": 0.39, "code": "PH"}
"name": "North America",
"color": "#ef1621",
"children": [
{"name": "United States", "weight": 24.32, "code": "US"},
{"name": "Canada", "weight": 2.09, "code": "CA"},
{"name": "Mexico", "weight": 1.54, "code": "MX"}
"name": "Europe",
"color": "#77bc45",
"children": [
{"name": "Germany", "weight": 4.54, "code": "DE"},
{"name": "United Kingdom", "weight": 3.85, "code": "UK"},
{"name": "France", "weight": 3.26, "code": "FR"},
{"name": "Italy", "weight": 2.46, "code": "IT"},
{"name": "Spain", "weight": 1.62, "code": "ES"},
{"name": "Netherlands", "weight": 1.01, "code": "NL"},
{"name": "Switzerland", "weight": 0.9, "code": "CH"},
{"name": "Sweden", "weight": 0.67, "code": "SE"},
{"name": "Poland", "weight": 0.64, "code": "PL"},
{"name": "Belgium", "weight": 0.61, "code": "BE"},
{"name": "Norway", "weight": 0.52, "code": "NO"},
{"name": "Austria", "weight": 0.51, "code": "AT"},
{"name": "Denmark", "weight": 0.4, "code": "DK"},
{"name": "Ireland", "weight": 0.38, "code": "IE"}
"name": "South America",
"color": "#4aaaea",
"children": [
{"name": "Brazil", "weight": 2.39, "code": "BR"},
{"name": "Argentina", "weight": 0.79, "code": "AR"},
{"name": "Venezuela", "weight": 0.5, "code": "VE"},
{"name": "Colombia", "weight": 0.39, "code": "CO"}
"name": "Australia",
"color": "#00acad",
"children": [
{"name": "Australia", "weight": 1.81, "code": "AU"}
"name": "Africa",
"color": "#f575a3",
"children": [
{"name": "Nigeria", "weight": 0.65, "code": "NG"},
{"name": "Egypt", "weight": 0.45, "code": "EG"},
{"name": "South Africa", "weight": 0.42, "code": "ZA"}
"name": "Rest of the World",
"color": "#592c94",
"children": [
{"name": "Rest of the World", "weight": 9.41, "code": "RotW"}
<!DOCTYPE html>
<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="" charset="utf-8"></script>
<script src=""></script>
<script src=""></script>
<script src=""></script>
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;
.hoverer:hover {
stroke-width: 3px;
.legend-color {
stroke-width: 1px;
//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.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").then(function(rootData) {
hierarchy = d3.hierarchy(rootData).sum(function(d){ return d.weight; });
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) {
[radius + radius*Math.cos(a), radius + radius*Math.sin(a)]
return circlingPolygon;
function initLayout(rootData) {
svg ="svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
drawingArea = svg.append("g")
.classed("drawingArea", true)
.attr("transform", "translate("+[margin.left,]+")");
treemapContainer = drawingArea.append("g")
.classed("treemap-container", true)
.attr("transform", "translate("+treemapCenter+")");
.classed("world", true)
.attr("transform", "translate("+[-treemapRadius,-treemapRadius]+")")
.attr("d", "M"+circlingPolygon.join(",")+"Z");
function drawTitle() {
.attr("id", "title")
.attr("transform", "translate("+[halfWidth, titleY]+")")
.attr("text-anchor", "middle")
.text("The Global Economy by GDP (as of 01/2017)")
function drawFooter() {
.classed("tiny light", true)
.attr("transform", "translate("+[0, height]+")")
.attr("text-anchor", "start")
.text("Remake of's article 'The Global Economy by GDP'")
.classed("tiny light", true)
.attr("transform", "translate("+[halfWidth, height]+")")
.attr("text-anchor", "middle")
.text("by @_Kcnarf")
.classed("tiny light", true)
.attr("transform", "translate("+[width, height]+")")
.attr("text-anchor", "end")
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")
var legend = legends.append("g")
.classed("legend", true)
.attr("transform", function(d,i){
return "translate("+[0, -i*(legendHeight+interLegend)]+")";
.classed("legend-color", true)
.attr("y", -legendHeight)
.attr("width", colorWidth)
.attr("height", legendHeight)
.style("fill", function(d){ return d.color; });
.classed("tiny", true)
.attr("transform", "translate("+[colorWidth+5, -2]+")")
.text(function(d){ return; });
.attr("transform", "translate("+[0, -continents.length*(legendHeight+interLegend)-5]+")")
function drawTreemap(hierarchy) {
var leaves=hierarchy.leaves();
var cells = treemapContainer.append("g")
.classed('cells', true)
.attr("transform", "translate("+[-treemapRadius,-treemapRadius]+")")
.classed("cell", true)
.attr("d", function(d){ return "M"+d.polygon.join(",")+"z"; })
.style("fill", function(d){
var labels = treemapContainer.append("g")
.classed('labels', true)
.attr("transform", "translate("+[-treemapRadius,-treemapRadius]+")")
.classed("label", true)
.attr("transform", function(d){
return "translate("+[,]+")";
.style("font-size", function(d){ return fontScale(; });
.classed("name", true)
return (<1)? :;
.classed("value", true)
.text(function(d){ return"%"; });
var hoverers = treemapContainer.append("g")
.classed('hoverers', true)
.attr("transform", "translate("+[-treemapRadius,-treemapRadius]+")")
.classed("hoverer", true)
.attr("d", function(d){ return "M"+d.polygon.join(",")+"z"; });
.text(function(d) { return + "\n" + d.value+"%"; });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment