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); });