This chart seeks to compare to two ways of mapping quantitative data using the choropleth technique and the cartogram. The Dorling cartogram method is employed here, which uses geometric shapes to represent the areas. This is not however, a true Dorling Cartogram, as some locality is preserved to aid with interpetation. The quantitative data for this is Carbon Dioxide emissions per capita within Europe from 2013.
TOPOjson data for this project was sourced from Mila Frerichs gist.github.com
While CO2 emissions data was sourced from the UN Databank
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/topojson@3"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
text.shadow {
stroke: white;
stroke-width: 2.5px;
opacity: 1;
}
.legend {
cursor: pointer;
}
</style>
</head>
<body>
<script>
var width = 960;
var height = 500;
var center = [10, 72];
var scale = 395;
var projection = d3.geoMercator()
.scale(scale)
.translate([width / 2, 0])
.center(center);
var path = d3.geoPath().projection(projection);
var svg = d3.select("body")
.append("svg")
.attr("height", height)
.attr("width", width);
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// Create linear colour gradient for choropleth using max min values and defined colours
var minimum = 1;
var maximum = 19;
var minimumColour = '#e0b2b3'
var maximumColour = '#ac484b';
var colour = d3.scaleLinear()
.domain([minimum, maximum])
.range([minimumColour, maximumColour]);
var g = svg.append("g");
g.append("rect")
.attr("class", "legend")
.attr("height", 100)
.attr("width", 220)
.attr("x", 15)
.attr("y", 360)
.style("fill", "#b5b5b5")
.style("opacity", 0.2)
.style("stroke", "#232323").style("stroke-width", "5")
// Create linear gradient defs within index
var defs = svg.append("defs")
// Define gradient direction along x axis
var gradient = defs.append("linearGradient")
.attr("id", "gradient")
.attr('x1', "0%")
.attr("y1", "0%")
.attr("x2", "100%")
.attr("y2", "0%")
gradient.append("stop")
.attr("class", "start")
.attr("offset", "0%")
.attr("stop-color", '#e0b2b3')
.attr("stop-opacity", 1);
gradient.append("stop")
.attr("class", "end")
.attr("offset", "100%")
.attr("stop-color", '#ac484b')
.attr("stop-opacity", 1);
// Create the rectangle that the linear gradient will be used to fill
g.append("rect")
.attr("class", "key")
.attr("id", "choropleth")
.attr("width", 200)
.attr("height", 40)
.style("fill", "url(#gradient)")
.style("opacity", 1)
.attr("transform", "translate(20,30)");
// Use scaleLinear function to create divisions for axis
var y = d3.scaleLinear()
.range([200, 0])
.domain([maximum, minimum]);
var yAxis = d3.axisBottom(y);
// Adding the axis and positioning it, while calling the yaxis function
g.append("g")
.attr("class", "key")
.attr("id", "choropleth")
.attr("transform", "translate(20,75)")
.call(yAxis)
.style("opacity", 1)
g.append("text")
.attr("class", "key")
.attr("id", "choropleth")
.style("opacity", 1)
.attr("transform", "translate(15, 105)")
.text("Metric Tonnes per Capita of CO2");
// Reading in the TOPOjson file containing the shapes, and the data within ins properties
d3.json("eu.json", function(data) {
g.selectAll(".country")
.data(topojson.feature(data, data.objects.eu).features)
.enter()
.append('path')
.attr('class', 'country')
.attr("id", "choropleth")
.attr('d', path)
.style("opacity", 1)
.style("fill", function (feature) {
return colour(feature.properties.data_2013_CO2_MTpc)
})
//Browser rendered tooltips
.append("svg:title")
.text(function(feature){ return ([feature.properties.name + ' ', ' ' + feature.properties.data_2013_CO2_MTpc + ' Metric tonnes per capita'])});
});
// The hide/show function, uses opacity to display active layer
g.append("text")
.attr("class", "legend")
.attr("x", 20)
.attr("y", 410)
.style("font-weight", "bold").style("font-size", "19px")
.on("click", function(){
//var active = choropleth.active ? false : true,
//nO = active ? 0 : 1;
d3.selectAll("#choropleth").style("opacity", 1);
d3.selectAll("#dorling").style("opacity", 0);
choropleth.active = true;
dorling.active = false;
})
.text(" > Europe Choropleth");
// Dorling cartogram section
var getX = function(feature){
return path.centroid(feature)[0];
};
var getY = function(feature){
return path.centroid(feature)[1];
};
var getEmissions = function(feature){
return(feature.properties.data_2013_CO2_MTpc *2 );
};
// Reads in TOPOjson file into path specified above, however displays circles based on polygon centroids using path.centroid
// Reads in TOPOjson file into path specified above, however displays circles based on polygon centroids using path.centroid
d3.json("eu.json", function(data) {
var geojson = topojson.feature(data, data.objects.eu).features;
var nodes = geojson.filter(function(d, i){
return (d.properties.data_2013_CO2_MTpc !== null);
})
.map(function(d){
//console.log(d);
var point = path.centroid(d);
var value = d.properties.data_2013_CO2_MTpc;
if (value === null) return {};
var obj = {
name: d.properties.name,
label: d.properties.iso_3,
x: point[0], y: point[1],
x0: point[0], y0: point[1],
r: value*2,
value: value
};
//console.log(obj);
return obj;
});
var simulation = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(3))
.force("collide", d3.forceCollide(function(d) {
return d.r;
}).strength(.1))
.on('tick', function() {
node
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
g.datum(nodes);
var node = g.selectAll("circle")
.data(function(d) { return d; })
.enter()
.append("circle")
.attr("id", "dorling")
.style("opacity", 0)
.attr("r", function(d) { return d.r; })
.attr("fill", function(d,i){ return "hsl(" + Math.random() * 360 + ",100%,50%)";});
node.append("svg:title")
.text(function(feature){ return ([feature.name + ' ', ' ' + feature.value + ' Metric tonnes per capita'])});
});
// Hide/show using specified ID
g.append("text")
.attr("class", "legend")
.attr("x", 20)
.attr("y", 445)
.style("font-weight", "bold").style("font-size", "19px")
.on("click", function(){
d3.selectAll("#choropleth").style("opacity", 0);
d3.selectAll("#dorling").style("opacity", 1);
choropleth.active = false;
dorling.active = true;
})
.text(" > Dorling Cartogram");
//Dorling legend item
g.append("rect")
.attr("class", "key")
.attr("id", "dorling")
.attr("height", 125)
.attr("width", 220)
.attr("x", 15)
.attr("y", 35)
.style("fill", "#ffffff")
.style("opacity", 0)
.style("stroke", "#232323").style("stroke-width", "5")
g.append("circle")
.attr("class", "key")
.attr("id", "dorling")
.attr("r", "40")
.attr("transform", "translate(120,90)")
.style("opacity", 0)
.style("fill", "none").style("stroke-width", "2").style("stroke", "grey")
g.append("circle")
.attr("class", "key")
.attr("id", "dorling")
.attr("r", "20")
.attr("transform", "translate(140,90)")
.style("opacity", 0)
.style("fill", "none").style("stroke-width", "2").style("stroke", "grey")
g.append("circle")
.attr("class", "key")
.attr("id", "dorling")
.attr("r", "10")
.attr("transform", "translate(150,90)")
.style("opacity", 0)
.style("fill", "none").style("stroke-width", "2").style("stroke", "grey")
g.append("text")
.attr("class", "key")
.attr("id", "dorling")
.attr("transform", "translate(95,95)")
.style("font-size", "14px")
.style("opacity", 0)
.text('20')
g.append("text")
.attr("class", "key")
.attr("id", "dorling")
.attr("transform", "translate(125,95)")
.style("font-size", "14px")
.style("opacity", 0)
.text('10')
g.append("text")
.attr("class", "key")
.attr("id", "dorling")
.attr("transform", "translate(147,95)")
.style("font-size", "14px")
.style("opacity", 0)
.text('5')
g.append("text")
.attr("class", "key")
.attr("id", "dorling")
.attr("transform", "translate(120, 150)")
.attr("text-anchor", "middle")
.style("font-size", "18px")
.style("opacity", 0)
.text("Metric tonnes per capita")
// Create legend border box
g.append("text")
.attr("class", "shadow")
.attr("x", 20)
.attr("y", 380)
.style("text-anchor", "start")
.style("font-size", "22px")
.style("font-weight", "bold")
.style("text-decoration", "underline")
.text("Select map to display")
g.append("text")
.attr("class", "legend")
.attr("x", 20)
.attr("y", 380)
.style("text-anchor", "start")
.style("font-size", "22px")
.style("font-weight", "bold")
.style("text-decoration", "underline")
.text("Select map to display")
</script>
</body>
https://d3js.org/d3.v4.min.js
https://unpkg.com/topojson@3