Using data from the International Telecommunication Union, the treemap illustrates in which regions and countries most unconnected people live.
In addition, it shows the progress made in bringing people online in the period 2010-2015.
Pending: enforce a smooth transition between 2010 and 2015 data, so that only the size of the treemap rectangles changes and there is no reshuffling.
Built with blockbuilder.org
forked from anonymous's block: Treemap - Non-Internet users
xxxxxxxxxx
<style>
form {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
svg {
font: 10px arial;
}
body {
font: 15px arial;
}
br.long {
line-height: 150%;
}
h1{
margin-left: 1em;
margin-top: 1em;
}
svg.legend{
font: 20px arial;
}
.node-value {
font-weight: normal;
}
.btn-group{
margin-left: 3em;
margin-top: 3em;
}
.btn-group .button {
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
cursor: pointer;
float: left;
}
.btn-group .button:hover {
background-color: #3e8e41;
}
.btn-group .buttonsel:hover {
background-color: #3e8e41;
}
#total{
padding-top: 10px;
text-indent: 100px;
font-weight: normal;
font-size: 20px;
}
.btn-group .buttonsel {
background-color: #4CAF55; /* Green */
border: 5px solid black;
color: white;
padding: 10px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
cursor: pointer;
float: left;
}
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
<body>
<h1> Non-Internet users by region and country, 2010-2015 </h1>
<div class="btn-group">
<button class="buttonsel" id="d2010" >2010</button>
<button class="button" id="d2015">2015</button>
<div id="total"> Total non-Internet users: <span id="tot_value"> </span> million</div>
</div>
<br style="clear:both">
<br>
<div class="chart">
</div>
<script>
var margin = {top: 30, right: 20, bottom: 0, left: 30},
margin_legend = {top: 30, left: 70},
width = 800,
height = 450,
data, root1, root2, duration_tips=700, duration_transitions=4000;
var d2015 = false;
var svg = d3.select(".chart")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
var color = d3.scaleOrdinal()
.domain(["Asia & Pacific", "Africa", "Arab States","The Americas","Europe","CIS"])
.range(["#e78ac3", "#a6d854" , "#ffd92f","#fc8d62","#66c2a5","#8da0cb"]);
var format = d3.format(",.2r")
format2 = d3.format(",.3r")
x_padding = 2
y_padding = 15;
var treemap = d3.treemap()
.tile(d3.treemapResquarify)
.size([width, height])
.round(true)
.paddingInner(1);
var nest1 = d3.nest()
.key(function(d) { return d.region; })
.key(function(d) { return d.iso; })
.key(function(d) { return d.country; })
.rollup(function(d) { return d3.sum(d, function(d) { return parseFloat(d.data2010); }); });
var nest2 = d3.nest()
.key(function(d) { return d.region; })
.key(function(d) { return d.iso; })
.key(function(d) { return d.country; })
.rollup(function(d) { return d3.sum(d, function(d) { return parseFloat(d.data2015); }); });
// read csv file & draw initial treemap
d3.csv("Non_Int_users.csv", function(error, csv_data) {
if (error) throw error;
data = csv_data;
var root1 = d3.hierarchy({values: nest1.entries(data)}, function(d) { return d.values; })
.sum(function(d) { return d.value; })
.sort(function(a, b) { return b.value - a.value; });
var root2 = d3.hierarchy({values: nest2.entries(data)}, function(d) { return d.values; })
.sum(function(d) { return d.value; })
.sort(function(a, b) { return b.value - a.value; });
treemap(root1);
treemap(root2);
var ratio = Math.sqrt(root1.value/root2.value)
var cell = svg.selectAll("g")
.data(root1.leaves())
.enter().append("g")
.attr("transform", function(d) { x= d.x0 +margin.left; y= d.y0 +margin.left; return "translate(" + x + "," + y + ")"; });
cell.append("rect")
.attr("id", function(d) { return d.parent.data.key; })
.attr("width", function(d) { return d.x1 - d.x0; })
.attr("height", function(d) { return d.y1 - d.y0; })
.attr("fill", function(d) { return color(d.parent.parent.data.key); });
cell.append("text")
.attr("class", "node-label")
.attr("x", function(d) { return d.dx; })
.attr("y", function(d) { return d.dy; })
.attr("cursor","default")
.attr("dy", y_padding + "px")
.attr("dx", x_padding + "px")
.call(fit_text,1);
cell.append("text")
.attr("class", "node-value")
.attr("cursor","default")
.attr("x", function(d) { return d.dx; })
.attr("y", function(d) { return d.dy; })
.attr("dy", 2*y_padding + "px")
.attr("dx", x_padding + "px")
.call(fit_value,1);
// Add legend according to selected colors
d3.select(".chart")
.append("svg")
.attr("class","legend")
.attr("width", "300")
.attr("height", height+ margin.top + margin.bottom);
legend = d3.select("svg.legend");
// Rank regions per non-users and draw legend from + to -
legend
.call(draw_legend,1,root1.children[0].data.key,margin_legend)
.call(draw_legend,2,root1.children[1].data.key,margin_legend)
.call(draw_legend,3,root1.children[2].data.key,margin_legend)
.call(draw_legend,4,root1.children[3].data.key,margin_legend)
.call(draw_legend,5,root1.children[4].data.key,margin_legend)
.call(draw_legend,6,root1.children[5].data.key,margin_legend);
// Write total figure at the top
d3.select("#tot_value")
.text(String(format(root1.value/1000000)));
// when clicking on 2015, transition to 2015 data
d3.select("#d2015").on("click", function() {
// update buttons
d3.select("#d2015").attr("class","buttonsel");
d3.select("#d2010").attr("class","button");
d2015 = true;
// update tree
cell.data(root2.leaves(),function(d){return d.parent.data.key})
.transition()
.duration(duration_transitions)
.attr("transform", function(d) { x= d.x0/ratio +margin.left; y= d.y0/ratio +margin.left; return "translate(" + x + "," + y + ")"; });
cell.data(root2.leaves(),function(d){return d.parent.data.key}).select("rect")
.transition()
.duration(duration_transitions)
.attr("width", function(d) { return (d.x1 - d.x0)/ratio; })
.attr("height", function(d) { return (d.y1 - d.y0)/ratio; })
.attr("stroke","white")
.attr("stroke-width","0.5");
cell.data(root2.leaves(),function(d){return d.parent.data.key}).select(".node-label")
.transition()
.delay(duration_transitions/2)
.attr("opacity",1)
.call(fit_text,ratio);
cell.data(root2.leaves(),function(d){return d.parent.data.key}).select(".node-value")
.transition()
.duration(duration_transitions/2)
.style("fill-opacity",1e-6);
cell.data(root2.leaves(),function(d){return d.parent.data.key}).select(".node-value")
.transition()
.delay(duration_transitions/2)
.call(fit_value,ratio)
.duration(duration_transitions/2)
.style("fill-opacity",1);
// Update legend
legend2 = d3.select("svg.legend");
// Rank regions per non-users and draw legend from + to -
legend2
.transition()
.duration(duration_transitions)
.call(update_legend,1,root2.children[0].data.key,margin_legend)
.call(update_legend,2,root2.children[1].data.key,margin_legend)
.call(update_legend,3,root2.children[2].data.key,margin_legend)
.call(update_legend,4,root2.children[3].data.key,margin_legend)
.call(update_legend,5,root2.children[4].data.key,margin_legend)
.call(update_legend,6,root2.children[5].data.key,margin_legend);
// Update total value counter
d3.select("#tot_value")
.transition()
.duration(duration_transitions)
.tween("text", function(d) {
var i = d3.interpolate(root1.value/1000000, root2.value/1000000);
return function(t) {
d3.select("#tot_value").text(format2(i(t)));
};
});
});
// when clicking on 2010, transition to 2010 data
d3.select("#d2010").on("click", function() {
// update buttons
d3.select("#d2015").attr("class","button");
d3.select("#d2010").attr("class","buttonsel");
d2015 = false;
// update treemap
cell.data(root1.leaves())
.transition()
.duration(duration_transitions)
.attr("transform", function(d) { x= d.x0 +margin.left; y= d.y0 +margin.left; return "translate(" + x + "," + y + ")"; });
cell.data(root1.leaves()).select("rect")
.transition()
.duration(duration_transitions)
.attr("width", function(d) { return d.x1 - d.x0; })
.attr("height", function(d) { return d.y1 - d.y0; })
.attr("stroke","white")
.attr("stroke-width","0.5");
cell.data(root1.leaves()).select(".node-label")
.transition()
.delay(duration_transitions/2)
.call(fit_text,1);
cell.data(root1.leaves()).select(".node-value")
.transition()
.duration(duration_transitions/2)
.style("fill-opacity",1e-6);
cell.data(root1.leaves()).select(".node-value")
.transition()
.delay(duration_transitions/2)
.call(fit_value,1)
.duration(duration_transitions/2)
.style("fill-opacity",1);
// update total value counter
d3.select("#tot_value")
.transition()
.duration(duration_transitions)
.tween("text", function(d) {
var i = d3.interpolate(root2.value/1000000, root1.value/1000000);
return function(t) {
d3.select("#tot_value").text(format2(i(t)));
};
});
});
});
// FUNCTIONS USED IN THE CODE ABOVE
function update_legend(selection, pos,text){
var selector = "rect[id='"+text+"']"
var selector2 = "text[id='"+text+"s"+"']"
selection
.select(selector)
.attr("y",function(d){return margin.top + 60*pos});
selection
.select(selector2)
.attr("y",function(d){return margin.top + 60*pos});
}
function draw_legend(selection, pos,text, margin){
selection
.append('rect')
.attr('id',text)
.attr("width", "20")
.attr("height", "20")
.attr("x", margin.left)
.attr("y",function(d){return margin.top + 60*pos})
.attr("fill", color(text));
selection
.append("text")
.attr('id',text+"s")
.attr("x", margin.left)
.attr("y",function(d){return margin.top + 60*pos})
.attr("dy", y_padding + "px")
.attr("dx", 15*x_padding + "px")
.text(text);
}
// Fits country name to the space in the treemap rectangle
function fit_text(selection,scale){
selection
.text( function(d){
var iso = String(d.parent.data.key).toUpperCase()
var fullname = String(d.data.key)
if((getTextWidth(fullname,15,"arial") < (((d.x1 - d.x0)-x_padding)/scale)) && (getTextWidth("l",15,"arial") < (((d.y1 - d.y0)-y_padding)/scale))) {
return(fullname)
}else if((getTextWidth(iso,15,"arial") < (((d.x1 - d.x0)-x_padding)/scale)) && (getTextWidth("l",15,"arial") < (((d.y1 - d.y0)-y_padding)/scale))){
return(iso)
}else if((getTextWidth(iso,9,"arial") < (((d.x1 - d.x0)-x_padding)/scale)) && (getTextWidth("l",9,"arial") < (((d.y1 - d.y0)-y_padding)/scale))){
return(iso)
}
})
.attr("font-size",function(d){
var iso = String(d.parent.data.key).toUpperCase()
if((getTextWidth(iso,15,"arial") < (((d.x1 - d.x0)-x_padding)/scale)) && (getTextWidth("l",15,"arial") < (((d.y1 - d.y0)-y_padding)/scale))){
return("15px")
} else{
return("9px")
}
});
}
// Fits country value to the space in the treemap rectangle
function fit_value(selection,scale){
selection
.text( function(d){
var text = String(format(d.value/1000000))+"M"
if((getTextWidth(text,15,"sans-serif") < (((d.x1 - d.x0)-x_padding)/scale)) && (getTextWidth("a",15,"sans-serif") < (((d.y1 - d.y0)-1.7*y_padding)/scale))) {
return(text)
}
})
}
function getTextWidth(text, fontSize, fontFace) {
var a = document.createElement('canvas');
var b = a.getContext('2d');
b.font = fontSize + 'px ' + fontFace;
return b.measureText(text).width;
}
</script>
</body>
https://d3js.org/d3.v4.min.js