Mapbox: h3 hexagons
by andriika
HTML
<link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css">
<script src="https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script>
<script src="https://unpkg.com/h3-js"></script>
<div id="map" style="width: 100%; height: 400px;"></div>
<div id="zoom"></div>
CSS
* {
margin: 0;
padding: 0;
}
JavaScript
mapboxgl.accessToken = 'pk.eyJ1IjoiYW5kcmlpa2EiLCJhIjoiY2tnazZsdjIzMDNqOTJ4cWVwbDByYjQ1byJ9.SgQz2ztP9STig7BU6d3Gew';
const center = [-118.302, 34.048];
const zoom = 15; // [6, 15] (10)
const h3resolution = 5; // [5, 11] (7)
// 6 - 5 - 5 + 0 * .7
// 7 - 5.7 - 5 + 1 * .7
// 8 - 6.4 - 5 + 2 * .7
// ..
// 15 - f(x) - 5 + (15 - 6) * .7
// f(x) = 5 + (x - 6) * .7
function f(x) {
return Math.floor(5 + (x - 6) * 0.7);
}
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
center,
zoom
});
const geometryFactory = {
h3index(h3index) {
return {
type: 'Polygon',
coordinates: [h3.h3ToGeoBoundary(h3index, true)]
}
},
bounds(b) {
return {
type: 'Polygon',
coordinates: [
[
[b.getWest(), b.getNorth()],
[b.getEast(), b.getNorth()],
[b.getEast(), b.getSouth()],
[b.getWest(), b.getSouth()],
[b.getWest(), b.getNorth()]
]
]
}
}
}
function generateFeatures(bounds, zoom) {
bounds = geometryFactory.bounds(bounds);
const h3indexes = h3.polyfill(bounds.coordinates, f(zoom), true);
const features = [];
for (const h3index of h3indexes) {
const center = h3.h3ToGeo(h3index);
features.push({
type: 'Feature',
geometry: geometryFactory.h3index(h3index),
properties: {
value: Math.random(),
centerLat: center[0],
centerLon: center[1]
}
});
}
return features;
}
map.on('load', () => {
map.addSource('h3', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: generateFeatures(map.getBounds(), map.getZoom())
}
});
map.addLayer({
id: 'h3',
source: 'h3',
type: 'fill',
layout: {},
paint: {
'fill-color': '#088',
'fill-opacity': ['get', 'value']
}
}, 'road-primary-case');
map.on('zoomend', function() {
document.getElementById('zoom').textContent = map.getZoom() + ' ::...