Small multiple bar charts of the 2017 General Election in a grid layout of London UK parliamentary constituencies. Layout my own. Hover over barcharts to reveal a tooltip.
forked from tlfrd's block: London Constituency Grid Layout
forked from tlfrd's block: London Small Multiples
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="london-grid.js"></script>
<style>
body {
margin: 0;
}
text {
font-family: monospace;
}
.label {
font-size: 10px;
}
.constituency .background {
fill: grey;
fill-opacity: 0.2;
}
div.tooltip {
position: absolute;
text-align: left;
padding: 5px;
font: 10px monospace;
background-color: rgba(255, 255, 255, .95);
border: 1px solid lightgray;
pointer-events: none;
width: 100px;
}
div.tooltip .result {
float: right;
}
div.tooltip .name {
font-weight: bold;
}
</style>
</head>
<body>
<script>
var cfg = {
gridLength: 11,
gridHeight: 10,
paddingX: 25,
paddingY: 15,
}
var margin = {top: 15, right: 100, bottom: 15, left: 100};
var width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var rectWidth = (width / cfg.gridLength) - cfg.paddingX,
rectHeight = (height / cfg.gridHeight) - cfg.paddingY;
var dataUrl = "results.json";
var colours = {
"Con": "#0087dc",
"Green": "#008066",
"Lab": "#d50000",
"LabCoop": "#d50000",
"LibDem": "#FDBB30",
"UKIP": "#B3009D"
};
var constituencies = svg.append("g").attr("class", "constituencies");
function calculateCoords(d) {
var x = d.position.x * (rectWidth + cfg.paddingX);
var y = d.position.y * (rectHeight + cfg.paddingY);
return [x, y];
}
// Only include data for five main parties
var filteredGeData = {};
d3.json(dataUrl, function(geData) {
for (var c in geData) {
var candidates = [];
for (var i in geData[c].candidates) {
if (colours[geData[c].candidates[i].party]) {
candidates.push(geData[c].candidates[i]);
}
}
filteredGeData[c] = {
ons: c,
name: geData[c].name,
candidates: candidates
};
}
var constituency = constituencies.selectAll("g")
.data(londonGrid)
.enter().append("g")
.attr("class", "constituency")
.attr("transform", d => "translate(" + [calculateCoords(d)[0], calculateCoords(d)[1]] + ")")
.on("mouseover", showLabel)
.on("mouseout", hideLabel);
constituency.append("rect")
.attr("class", "background")
.attr("width", rectWidth)
.attr("height", rectHeight);
constituency.each(addBarchart);
});
function addBarchart(d) {
var barchart = d3.select(this),
results = filteredGeData[d.ons_code];
var x = d3.scaleBand()
.domain(results.candidates.map(d => d.party))
.range([0, rectWidth]);
var y = d3.scaleLinear()
.domain([0, 100])
.range([rectHeight, 0]);
var bars = barchart.append("g")
.selectAll("rect")
.data(results.candidates)
.enter().append("rect")
.attr("x", d => x(d.party))
.attr("y", d => y(d.percentageShare))
.attr("width", x.bandwidth())
.attr("height", d => rectHeight - y(d.percentageShare))
.style("fill", d => colours[d.party]);
var label = barchart.append("text")
.attr("class", "label")
.attr("x", rectWidth)
.attr("dx", -rectWidth / 3)
.attr("dy", rectHeight / 3)
.text(d => d.name.slice(0, 2));
}
function showLabel(d) {
var left = calculateCoords(d)[0],
right = calculateCoords(d)[1];
var candidates = filteredGeData[d.ons_code].candidates;
var html = "<span class='name'>" + filteredGeData[d.ons_code].name + "</span></br></br>";
candidates.forEach(function(c) {
html += c.party;
html += "<span class='result'>" + Math.round(c.percentageShare) + "%</span>";
html += "</br>";
});
div.transition()
.duration(200)
.style("opacity", 1)
div.html(html)
.style("left", (left + margin.left + rectWidth + 10) + "px")
.style("top", (right + margin.top) + "px")
}
function hideLabel(d) {
div.transition()
.duration(200)
.style("opacity", 0)
}
</script>
</body>
https://d3js.org/d3.v4.min.js