|
function ready(geo, userData) { |
|
// Some set up. |
|
const width = 900; |
|
const height = 500; |
|
const extentUk = [[0, height * 0.05], [width, height * 0.95]]; |
|
const pr = window.devicePixelRatio || 1; |
|
|
|
// Crisp canvas and context. |
|
const canvas = d3.select('canvas') |
|
.attr('width', width * pr) |
|
.attr('height', height * pr) |
|
.style('width', `${width}px`); |
|
const context = canvas.node().getContext('2d'); |
|
context.scale(pr, pr); |
|
|
|
// Background. |
|
context.fillStyle = '#02154e'; |
|
context.fillRect(0, 0, width, height); |
|
|
|
// Projection and path. |
|
const projection = d3.geoConicEqualArea() |
|
.parallels([50, 61]) |
|
.fitExtent(extentUk, geo); |
|
|
|
const geoPath = d3.geoPath() |
|
.projection(projection) |
|
.context(context); |
|
|
|
// Prep user data. |
|
userData.forEach(site => { |
|
const coords = projection([+site.lng, +site.lat]); |
|
site.x = coords[0]; |
|
site.y = coords[1]; |
|
}); |
|
|
|
// Remove non UK mainland sites. |
|
const poly = d3.geoPolygon(geo, projection); |
|
userData = d3.polygonPoints(userData, poly); |
|
|
|
// Hexgrid generator. |
|
const hexgrid = d3.hexgrid() |
|
.extent(extentUk) |
|
.geography(geo) |
|
.projection(projection) |
|
.pathGenerator(geoPath) |
|
.hexRadius(3); |
|
|
|
// Hexgrid instanace. |
|
const hex = hexgrid(userData); |
|
|
|
// Colour scale. |
|
const counts = hex.grid.layout |
|
.map(el => el.datapointsWt) |
|
.filter(el => el > 0); |
|
const ckBreaks = ss.ckmeans(counts, 4).map(clusters => clusters[0]); |
|
const colour = d3.scaleThreshold() |
|
.domain(ckBreaks) |
|
.range(['#fff9f9', '#fbb1b0', '#fc8584', '#fd5958', '#fe2c2c', 'crimson']); |
|
|
|
// Draw prep. |
|
const hexagon = new Path2D(hex.hexagon()); |
|
|
|
// Draw. |
|
hex.grid.layout.forEach(hex => { |
|
context.save(); |
|
context.translate(hex.x, hex.y); |
|
context.fillStyle = colour(hex.datapointsWt); |
|
context.fill(hexagon); |
|
context.restore(); |
|
}); |
|
} |
|
|
|
// Load data. |
|
const uk = d3.json( |
|
'https://raw.githubusercontent.com/larsvers/map-store/master/GBR_adm0_topo.json' |
|
); |
|
const points = d3.csv( |
|
'https://raw.githubusercontent.com/larsvers/data-store/master/postbox_locations_uk.csv' |
|
); |
|
|
|
Promise.all([uk, points]).then(res => { |
|
let [geoData, userData] = res; |
|
|
|
// Turn Topo to GeoJSON. |
|
const ukGeo = topojson.feature(geoData, geoData.objects.GBR_adm0); |
|
|
|
ready(ukGeo, userData); |
|
}); |