style: white land, gray sea, no roads/cities, country names zoom 3+
All checks were successful
Deploy Internet for Kids / Build & Push (push) Successful in 14s
Deploy Internet for Kids / Deploy (push) Successful in 6s
Deploy Internet for Kids / Health Check (push) Successful in 2s
Deploy Internet for Kids / Smoke Tests (push) Successful in 2s
Deploy Internet for Kids / IndexNow Ping (push) Successful in 7s
Deploy Internet for Kids / Promote to Latest (push) Successful in 2s
Deploy Internet for Kids / Rollback (push) Has been skipped
Deploy Internet for Kids / Audit (push) Successful in 2s
All checks were successful
Deploy Internet for Kids / Build & Push (push) Successful in 14s
Deploy Internet for Kids / Deploy (push) Successful in 6s
Deploy Internet for Kids / Health Check (push) Successful in 2s
Deploy Internet for Kids / Smoke Tests (push) Successful in 2s
Deploy Internet for Kids / IndexNow Ping (push) Successful in 7s
Deploy Internet for Kids / Promote to Latest (push) Successful in 2s
Deploy Internet for Kids / Rollback (push) Has been skipped
Deploy Internet for Kids / Audit (push) Successful in 2s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -54,6 +54,26 @@ body { margin: 0; overflow: hidden; }
|
|||||||
});
|
});
|
||||||
|
|
||||||
_ifkMap.on('load', function() {
|
_ifkMap.on('load', function() {
|
||||||
|
// White land, gray sea
|
||||||
|
_ifkMap.setPaintProperty('background', 'background-color', '#ffffff');
|
||||||
|
try { _ifkMap.setPaintProperty('water', 'fill-color', '#c8d3df'); } catch(e) {}
|
||||||
|
// Clean map: white land, no roads, no city labels — only country names + borders
|
||||||
|
_ifkMap.getStyle().layers.forEach(function(l) {
|
||||||
|
if (l.id.includes('land') && l.type === 'fill') _ifkMap.setPaintProperty(l.id, 'fill-color', '#ffffff');
|
||||||
|
// Hide roads/transport
|
||||||
|
if (l.type === 'line' && (l.id.includes('road') || l.id.includes('rail') || l.id.includes('transit') || l.id.includes('tunnel') || l.id.includes('bridge') || l.id.includes('transport') || l.id.includes('highway') || l.id.includes('path') || l.id.includes('aeroway'))) {
|
||||||
|
try { _ifkMap.setLayoutProperty(l.id, 'visibility', 'none'); } catch(e) {}
|
||||||
|
}
|
||||||
|
// Hide all symbol layers except country labels (show at zoom 3+)
|
||||||
|
if (l.type === 'symbol') {
|
||||||
|
if (l.id.includes('country')) {
|
||||||
|
try { _ifkMap.setLayerZoomRange(l.id, 3, 24); } catch(e) {}
|
||||||
|
} else {
|
||||||
|
try { _ifkMap.setLayoutProperty(l.id, 'visibility', 'none'); } catch(e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Promise.all([
|
Promise.all([
|
||||||
fetch('/data/countries.json').then(function(r) { return r.json(); }),
|
fetch('/data/countries.json').then(function(r) { return r.json(); }),
|
||||||
fetch('/data/countries-50m.json').then(function(r) { return r.json(); })
|
fetch('/data/countries-50m.json').then(function(r) { return r.json(); })
|
||||||
@@ -72,46 +92,81 @@ body { margin: 0; overflow: hidden; }
|
|||||||
f.properties.isoNum = id;
|
f.properties.isoNum = id;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Render choropleth to a canvas, then add as single image source (NOT tiled)
|
// Render choropleth as image overlay — re-renders at high res for visible area
|
||||||
var W = 2048, H = 1024;
|
var MAX_LAT = 85.051129;
|
||||||
var offscreen = document.createElement('canvas');
|
var offscreen = document.createElement('canvas');
|
||||||
offscreen.width = W; offscreen.height = H;
|
var dpr = window.devicePixelRatio || 1;
|
||||||
var ctx = offscreen.getContext('2d');
|
|
||||||
|
|
||||||
// Draw country fills using Equirectangular projection
|
function mercY(lat, north, south, H) {
|
||||||
geo.features.forEach(function(f) {
|
var toMerc = function(l) { var r = l * Math.PI / 180; return Math.log(Math.tan(Math.PI/4 + r/2)); };
|
||||||
var id = String(f.id).padStart(3, '0');
|
var mTop = toMerc(north), mBot = toMerc(south);
|
||||||
var c = byIsoNum[id];
|
return (toMerc(north) - toMerc(lat)) / (mTop - mBot) * H;
|
||||||
if (!c) return;
|
}
|
||||||
ctx.fillStyle = STATUS_COLORS[c.status];
|
|
||||||
ctx.beginPath();
|
function renderChoropleth() {
|
||||||
var coords = f.geometry.type === 'Polygon' ? [f.geometry.coordinates] : f.geometry.coordinates;
|
var bounds = _ifkMap.getBounds();
|
||||||
coords.forEach(function(poly) {
|
var west = Math.max(-180, bounds.getWest());
|
||||||
poly.forEach(function(ring) {
|
var east = Math.min(180, bounds.getEast());
|
||||||
for (var i = 0; i < ring.length; i++) {
|
var south = Math.max(-MAX_LAT, bounds.getSouth());
|
||||||
var x = (ring[i][0] + 180) / 360 * W;
|
var north = Math.min(MAX_LAT, bounds.getNorth());
|
||||||
var y = (90 - ring[i][1]) / 180 * H;
|
// Pad bounds slightly
|
||||||
if (i === 0) ctx.moveTo(x, y);
|
var lonPad = (east - west) * 0.1;
|
||||||
else ctx.lineTo(x, y);
|
var latPad = (north - south) * 0.1;
|
||||||
}
|
west = Math.max(-180, west - lonPad);
|
||||||
ctx.closePath();
|
east = Math.min(180, east + lonPad);
|
||||||
|
south = Math.max(-MAX_LAT, south - latPad);
|
||||||
|
north = Math.min(MAX_LAT, north + latPad);
|
||||||
|
|
||||||
|
var container = _ifkMap.getContainer();
|
||||||
|
var W = Math.round(container.clientWidth * dpr);
|
||||||
|
var H = Math.round(container.clientHeight * dpr);
|
||||||
|
offscreen.width = W; offscreen.height = H;
|
||||||
|
var ctx = offscreen.getContext('2d');
|
||||||
|
ctx.clearRect(0, 0, W, H);
|
||||||
|
|
||||||
|
geo.features.forEach(function(f) {
|
||||||
|
var id = String(f.id).padStart(3, '0');
|
||||||
|
var c = byIsoNum[id];
|
||||||
|
if (!c) return;
|
||||||
|
ctx.fillStyle = STATUS_COLORS[c.status];
|
||||||
|
ctx.beginPath();
|
||||||
|
var coords = f.geometry.type === 'Polygon' ? [f.geometry.coordinates] : f.geometry.coordinates;
|
||||||
|
coords.forEach(function(poly) {
|
||||||
|
poly.forEach(function(ring) {
|
||||||
|
for (var i = 0; i < ring.length; i++) {
|
||||||
|
var lon = ring[i][0], lat = Math.max(-MAX_LAT, Math.min(MAX_LAT, ring[i][1]));
|
||||||
|
var x = (lon - west) / (east - west) * W;
|
||||||
|
var y = mercY(lat, north, south, H);
|
||||||
|
if (i === 0) ctx.moveTo(x, y);
|
||||||
|
else ctx.lineTo(x, y);
|
||||||
|
}
|
||||||
|
ctx.closePath();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
ctx.fill();
|
||||||
});
|
});
|
||||||
ctx.fill();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add as image source — single image, NO tiling
|
var url = offscreen.toDataURL('image/png');
|
||||||
_ifkMap.addSource('choropleth-img', {
|
var coords = [[west, north], [east, north], [east, south], [west, south]];
|
||||||
type: 'image',
|
|
||||||
url: offscreen.toDataURL('image/png'),
|
if (_ifkMap.getSource('choropleth-img')) {
|
||||||
coordinates: [[-180, 85.05], [180, 85.05], [180, -85.05], [-180, -85.05]]
|
_ifkMap.getSource('choropleth-img').updateImage({ url: url, coordinates: coords });
|
||||||
});
|
} else {
|
||||||
_ifkMap.addLayer({
|
_ifkMap.addSource('choropleth-img', { type: 'image', url: url, coordinates: coords });
|
||||||
id: 'choropleth-fill',
|
// Find first label/symbol layer to insert choropleth below it
|
||||||
type: 'raster',
|
var firstLabel = null;
|
||||||
source: 'choropleth-img',
|
_ifkMap.getStyle().layers.forEach(function(l) {
|
||||||
paint: { 'raster-opacity': 0.85, 'raster-fade-duration': 0 }
|
if (!firstLabel && (l.type === 'symbol')) firstLabel = l.id;
|
||||||
});
|
});
|
||||||
|
_ifkMap.addLayer({
|
||||||
|
id: 'choropleth-fill', type: 'raster', source: 'choropleth-img',
|
||||||
|
paint: { 'raster-opacity': 0.85, 'raster-fade-duration': 0 }
|
||||||
|
}, firstLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderChoropleth();
|
||||||
|
_ifkMap.on('moveend', renderChoropleth);
|
||||||
|
|
||||||
// Keep GeoJSON source for hover/click interaction (invisible)
|
// Keep GeoJSON source for hover/click interaction (invisible)
|
||||||
_ifkMap.addSource('countries', { type: 'geojson', data: geo });
|
_ifkMap.addSource('countries', { type: 'geojson', data: geo });
|
||||||
|
|||||||
Reference in New Issue
Block a user