Skip to content

Instantly share code, notes, and snippets.

@larsvers
Last active November 23, 2019 07:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save larsvers/a05405dd9476e5842a1dbbc93b3d1cf7 to your computer and use it in GitHub Desktop.
Save larsvers/a05405dd9476e5842a1dbbc93b3d1cf7 to your computer and use it in GitHub Desktop.
A lot of post boxes - with d3-hexgrid
license: mit
height: 500
border: no
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);
});
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Post boxes</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- d3-hexgrid script comes first. -->
<script src="//unpkg.com/d3-hexgrid"></script>
<script src="//unpkg.com/d3"></script>
<script src="//unpkg.com/d3-geo-projection"></script>
<script src='//unpkg.com/simple-statistics'></script>
<script src='//unpkg.com/topojson'></script>
</head>
<body>
<div id="container">
<canvas></canvas>
</div>
<script src="app.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment