Makeover Monday - week 22 (http://www.makeovermonday.co.uk/data/)
Incorporates the 'glow' effect from Nadieh Bremer's Datasketch for Royal Families (http://www.datasketch.es/october/code/nadieh/)
The chart applied d3.transition() to the stdDeviation attribute on the feGaussianBlur element to affect the focus of the circles that have that filter applied to it.
Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Work+Sans" rel="stylesheet">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<style>
body { margin:0;top:0;right:0;bottom:0;left:30; font-family: 'Work Sans', sans-serif; background: black }
p, h1, li { color: white }
.domain { display: none; }
.tick text { fill: #808080 }
.axis-label { fill: #808080; font-size: 12; }
.tick line { stroke: #808080; shape-rendering: crispEdges; }
circle { cursor: pointer }
</style>
</head>
<body>
<h1>Growth in internet usage between 2010 and 2015</h1>
<p>As countries near peak internet usage, the yearly growth rate has to drop off.</p>
<p>However, looking at lower usage countries, we can see the countries that have been improving more rapidly than their counterparts.</p>
<p>Overview:</p>
<ul>
<li>Click the legend to focus on particular regions</li>
<li>Circle size corresponds to countries' population</li>
</ul>
<div id="chart"></div>
<script>
var maxX, maxY, maxR;
const x = "users_2015";
const y = "change";
const r = "population";
const defaultStdDev = 1.5;
const defaultOpacity = 0.8;
const width = 500;
const height = width;
const margin = {"top": 50, "left": 60, "right": 200, "bottom": 50,}
var colour = d3.scaleOrdinal(d3.schemeSet2);
var radius = d3.scaleSqrt()
.range([3,9])
var xScale = d3.scaleLinear()
.range([0,width]);
var yScale = d3.scaleLog()
.range([height, 0]);
var xAxis = d3.axisBottom(xScale);
var yAxis = d3.axisLeft(yScale)
.tickValues([0.01,0.1,0.5,1,10,20,40,80])
.tickFormat(formatLog);
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom);
//Container for the gradients
var defs = svg.append("defs");
d3.csv("data.csv", convertTextToNumbers, function(error, data) {
if(error) { throw error; };
maxX = d3.max(data, function(d){ return d[x]; });
maxY = d3.max(data, function(d){ return d[y]; });
maxR = d3.max(data, function(d){ return d[r]; });
xScale.domain([0,100]);
yScale.domain([0.001,maxY]);
radius.domain([0,maxR]);
//Code taken from https://www.datasketch.es/october/code/nadieh/ and https://stackoverflow.com/questions/9630008/how-can-i-create-a-glow-around-a-rectangle-with-svg
//Filter for the outside glow
var nestByRegion = d3.nest()
.key(function(d) { return d.regionTrimmed; })
.entries(data);
var filters = defs.selectAll("filter")
.data(nestByRegion)
.enter()
.append("filter")
.attr("width", "300%")
.attr("x", "-100%")
.attr("height", "300%")
.attr("y", "-100%")
.attr("id", function(d){ return d.key + "-glow"; })
var blurs = filters.append("feGaussianBlur")
.attr("class", "blur")
.attr("stdDeviation", defaultStdDev)
.attr("result", "coloredBlur");
var xAxisG = svg.append("g")
.attr("transform", "translate(" + (margin.left) + "," + (margin.top + height) + ")")
.call(xAxis);
xAxisG.append("text")
.text("% usage in 2015")
.attr("fill", "white")
.attr("x", width + 10)
.attr("y", -10)
.style("text-anchor", "end")
var yAxisG = svg.append("g")
.attr("transform", "translate(" + (margin.left) + "," + margin.top + ")")
.call(yAxis);
yAxisG.append("text")
.text("% growth from 2010 to 2015")
.attr("fill", "white")
.attr("x", -37)
.attr("y", -15)
.style("text-anchor", "start")
yAxisG.selectAll(".tick").selectAll("line")
.attr("x2", width)
.style("opacity", 0.5)
var g = svg.append("g")
.attr("transform", "translate(" + (margin.left) + "," + margin.top + ")");
var circles = g.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("class", "user-circle")
.attr("transform", function(d) {
return "translate(" + xScale(d[x]) + "," + yScale(d[y]) +")";
})
.attr("id", function(d,i){ return "circle-" + i }) ;
circles.append("circle")
.attr("r", function(d){ return radius(d[r]); })
.attr("cx", 0)
.attr("cy", 0)
.style("fill", function(d) { return colour(d.region) })
.style("opacity", defaultOpacity)
.style("filter",function(d) {
return "url(#" + d.regionTrimmed + "-glow)"
})
.on("mouseover", function(d){
circles.selectAll("text").style("opacity",0);
d3.select(this.parentNode).select("text").style("opacity",1);
})
.on("mouseout", function(d){
circles.selectAll("text").style("opacity",0);
});
circles.append("text")
.text(function(d) { return d.country })
.attr("x", 5)
.attr("y", -5)
.style("fill", "white")
.style("opacity", 0)
.style("pointer-events", "none");
var legend = svg.append("g")
.attr("transform", "translate("+(width + margin.left + 30)+",55)");
var legendEntries = legend.selectAll(".legend-items")
.data(colour.domain())
.enter()
.append("g")
.attr("transform", function(d, i){
return "translate(0," + (i * 18) + ")"
});
legendEntries.append("circle")
.attr("r", 5)
.attr("cx", 0)
.attr("cy", 0)
.style("fill", function(d) { return colour(d) })
.style("filter",function(d) { return "url(#" + removeWhiteSpace(d) + "-glow)"; })
.on("click", function(d){
circles.selectAll("circle")
.attr("pointer-events", function(c) {
return d == c.region ? "all" : "none";
})
.transition()
.style("opacity",function(c) {
return d == c.region ? 1 : 0.2;
});
blurs.transition()
.attr("stdDeviation", function(b) {
return b.key == removeWhiteSpace(d) ? 0.8 : 3;
});
});
legendEntries.append("text")
.text(function(d) { return d})
.attr("x", 11)
.attr("y", 5)
.style("fill", "white");
legend.append("text")
.text("Reset")
.attr("y", (colour.domain().length * 20))
.attr("x", 11)
.style("fill", "grey")
.on("click", function(d){
circles.selectAll("circle")
.style("opacity", defaultOpacity)
.attr("pointer-events", "default");
blurs.transition()
.attr("stdDeviation", defaultStdDev);
});
});
function convertTextToNumbers(d) {
d.regionTrimmed = removeWhiteSpace(d.region);
d.change = +d.change;
d.population = +d.population;
d.users_2015 = +d.users_2015;
d.users_2010 = +d.users_2010;
return d;
};
function formatLog(n){
return d3.format("0.2f")(n);
};
function removeWhiteSpace(str){
return str.replace(/\s/g, '');
};
</script>
</body>
https://d3js.org/d3.v4.min.js
https://d3js.org/d3-scale-chromatic.v1.min.js