Skip to content

Instantly share code, notes, and snippets.

@larsvers
Last active January 9, 2023 11:16
Show Gist options
  • Save larsvers/da5b2b77c8626be757076807409b87d3 to your computer and use it in GitHub Desktop.
Save larsvers/da5b2b77c8626be757076807409b87d3 to your computer and use it in GitHub Desktop.
Number of cities - with d3-hexgrid
license: mit
height: 500
border: no
function ready(geo, userData) {
// Some set up.
const width = 900;
const height = 500;
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.
const gradient = context.createRadialGradient(width / 2, height / 2, 5, width / 2, height / 2, width / 2);
gradient.addColorStop(0, '#0C2648');
gradient.addColorStop(1, '#091426');
context.fillStyle = gradient;
context.fillRect(0, 0, width, height);
// Projection and path.
const projection = d3.geoRobinson().fitSize([width, height], 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];
});
// Hexgrid generator.
const hexgrid = d3.hexgrid()
.extent([width, height])
.geography(geo)
.projection(projection)
.pathGenerator(geoPath)
.hexRadius(2);
// 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(['#293e5a', '#5e6d7c', '#929b9f', '#c7cac1', '#fbf8e3']);
// 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 world = d3.json(
'https://raw.githubusercontent.com/larsvers/map-store/master/earth-lands-10km.json'
);
const points = d3.csv(
'https://raw.githubusercontent.com/larsvers/data-store/master/cities_top_10000_world.csv'
);
Promise.all([world, points]).then(res => {
let [geoData, userData] = res;
ready(geoData, userData);
});
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Cities</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>
</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