A Joymap of London population per km^2
xxxxxxxxxx
<html>
<head>
<style>
.mode-btn {
position: absolute;
top: 15px;
left: 15px;
}
body {
font-family: monospace;
}
svg {
background-color: #ddd;
}
.line {
fill: none;
stroke-width: 2;
}
.constituency {
fill: black;
opacity: 0.1;
}
</style>
</head>
<body>
<a href="#" class="mode-btn">Toggle Dark Mode</a>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/topojson@3"></script>
<script>
var yOffset = 0.33;
function row(d) {
return {
x: +d.x,
y: +d.y,
population: +d.population
};
}
d3.queue()
.defer(d3.csv, 'population.csv', row)
.defer(d3.json, 'osgb36wpc.json')
.await(ready);
var darkMode = true;
d3.select('.mode-btn')
.on("click", function() {
d3.event.preventDefault();
if (!darkMode) {
darkMode = true;
d3.selectAll('.area')
.attr('fill', 'url(#svgGradient)');
d3.selectAll('.line')
.attr('stroke', 'url(#svgGradient)');
d3.select('.outline')
.attr('fill', 'black');
} else {
darkMode = false;
d3.selectAll('.area')
.attr('fill', '#ddd');
d3.selectAll('.line')
.attr('stroke', 'black');
d3.select('.outline')
.attr('fill', '#ddd');
}
});
function ready(error, data, gb) {
if (error) throw error;
var merged = topojson.merge(gb, gb.objects.osgb36wpc.geometries);
var constituencies = topojson.feature(gb, gb.objects.osgb36wpc);
var svg = d3.select('svg'),
width = +svg.attr('width'),
height = +svg.attr('height'),
extent = [[0, 20],[width, height - 20]];
var defs = svg.append("defs");
var gradient = defs.append("linearGradient")
.attr("id", "svgGradient")
.attr("x1", "0%")
.attr("x2", "0%")
.attr("y1", "0%")
.attr("y2", "100%");
gradient.append("stop")
.attr('class', 'start')
.attr("offset", "0%")
.attr("stop-color", "red")
.attr("stop-opacity", 1);
gradient.append("stop")
.attr('class', 'end')
.attr("offset", "100%")
.attr("stop-color", "blue")
.attr("stop-opacity", 1);
var projection = d3.geoIdentity()
.reflectY(true)
.fitExtent(extent, merged);
var path = d3.geoPath()
.projection(projection);
svg.append('path')
.datum(merged)
.attr('d', path)
.attr('class', 'outline')
.attr('fill', 'black');
svg.selectAll('.constituency')
.data(constituencies.features)
.enter().append('path')
.attr('class', 'constituency')
.attr('d', path);
svg.append('defs').append('clipPath').attr('id', 'gb-border')
.append('path').datum(merged)
.attr('d', path);
var tx = projection.translate()[0],
ty = projection.translate()[1],
k = projection.scale(),
x = function(d) { return (d * k) + tx; },
y = function(d) { return (d * -k) + ty; };
var dy = d3.scaleLinear()
.domain([0, d3.max(data, function(d) { return d.population; })])
.range([0, -height * yOffset / 6]);
var curve = d3.curveCardinal.tension(0);
var line = d3.line()
.x(function(d) { return x(d.x); })
.y(function(d) { return dy(d.population); })
.curve(curve);
var area = d3.area()
.x(function(d) { return x(d.x); })
.y0(dy(0))
.y1(function(d) { return dy(d.population); })
.curve(curve);
var lineData = d3.nest()
.key(function(d) { return d.y; })
.entries(data);
var lump = svg.append('g').attr('class', 'lumps')
.attr('clip-path', 'url(#gb-border)')
.selectAll('.lump').data(lineData)
.enter().append('g')
.attr('class', 'lump')
.attr('transform', function(d) { return 'translate(0,' + y(+d.key) + ')'})
.datum(function(d) { return d.values; });
lump.append('path')
.attr('class', 'area')
.attr('d', area)
.attr('fill', 'url(#svgGradient)');
lump.append('path')
.attr('class', 'line')
.attr('d', line)
.attr('stroke', 'url(#svgGradient)');
}
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js
https://unpkg.com/topojson@3