Files
EMERGENCY/skel/maps/www/index.html
T
2026-06-30 18:30:24 +00:00

120 lines
4.4 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>The Dark Elite - Maps</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.css
<script src="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js"></script>
<script src="https://unpkg.com/pmtiles@3.2.1/dist/pmtiles.js"></script>
<script src="https://unpkg.com/protomaps-themes-base@4.3.0/dist/protomaps-themes-base.js"></script>
<style>
body { margin: 0; padding: 0; background: #060708; font-family: system-ui, sans-serif; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
#header {
position: absolute; top: 0; left: 0; right: 0; z-index: 10;
background: rgba(6,7,8,0.85); color: #e5e7eb;
padding: 10px 16px; border-bottom: 1px solid rgba(34,211,238,0.25);
display: flex; justify-content: space-between; align-items: center;
backdrop-filter: blur(8px);
}
#header .left { display: flex; gap: 1rem; align-items: center; }
#header a { color: #9ca3af; text-decoration: none; font-size: 0.85rem; }
#header a:hover { color: #22d3ee; }
#header strong { color: #22d3ee; letter-spacing: 0.2em; text-transform: uppercase; font-size: 0.9rem; text-shadow: 0 0 8px rgba(34,211,238,0.4); }
#layers {
display: flex; gap: 0.4rem;
}
#layers button {
background: rgba(18,20,24,0.9); color: #e5e7eb;
border: 1px solid rgba(80,90,100,0.3); border-radius: 4px;
padding: 0.35rem 0.8rem; font-size: 0.75rem; cursor: pointer;
letter-spacing: 0.1em; text-transform: uppercase;
font-family: ui-monospace, monospace;
}
#layers button.active {
border-color: #22d3ee; color: #22d3ee;
box-shadow: 0 0 12px rgba(34,211,238,0.25);
}
#layers button:hover:not(.active) { border-color: rgba(34,211,238,0.5); }
</style>
</head>
<body>
<div id="header">
<div class="left"><strong>Maps</strong></div>
<div style="display:flex;gap:0.75rem;align-items:center"><div id="layers">
<button data-mode="base" class="active">Street</button>
<button data-mode="terrain">Topo</button>
</div><a href="/" style="color:#9ca3af;text-decoration:none;font-size:0.85rem">← Hub</a></div>
</div>
<div id="map"></div>
<script>
const protocol = new pmtiles.Protocol();
maplibregl.addProtocol("pmtiles", protocol.tile);
const map = new maplibregl.Map({
container: 'map',
style: {
version: 8,
glyphs: 'https://protomaps.github.io/basemaps-assets/fonts/{fontstack}/{range}.pbf',
sprite: 'https://protomaps.github.io/basemaps-assets/sprites/v4/dark',
sources: {
protomaps: { type: 'vector', url: 'pmtiles:///maps/base.pmtiles' },
terrain: { type: 'raster-dem', url: 'pmtiles:///maps/terrain.pmtiles', tileSize: 512, encoding: 'terrarium', maxzoom: 12 }
},
layers: protomaps_themes_base.default('protomaps', 'dark')
},
center: [-97.0, 39.0],
zoom: 4
});
map.addControl(new maplibregl.NavigationControl());
map.addControl(new maplibregl.ScaleControl());
map.on('load', () => {
// Add hillshade layer (initially hidden)
map.addLayer({
id: 'hillshade',
type: 'hillshade',
source: 'terrain',
layout: { visibility: 'none' },
paint: {
'hillshade-exaggeration': 0.6,
'hillshade-shadow-color': '#000000',
'hillshade-highlight-color': '#ffffff',
'hillshade-accent-color': '#22d3ee'
}
}, map.getStyle().layers[1].id);
setMode('base');
});
function setMode(mode) {
document.querySelectorAll('#layers button').forEach(b => {
b.classList.toggle('active', b.dataset.mode === mode);
});
const vectorLayers = map.getStyle().layers.filter(l => l.source === 'protomaps').map(l => l.id);
if (mode === 'base') {
map.setLayoutProperty('hillshade', 'visibility', 'none');
vectorLayers.forEach(id => map.setLayoutProperty(id, 'visibility', 'visible'));
if (map.getTerrain()) map.setTerrain(null);
} else if (mode === 'terrain') {
map.setLayoutProperty('hillshade', 'visibility', 'visible');
vectorLayers.forEach(id => {
// Keep only labels and roads visible for context
const layer = map.getStyle().layers.find(l => l.id === id);
const keep = layer && (layer.type === 'symbol' || id.includes('roads') || id.includes('water'));
map.setLayoutProperty(id, 'visibility', keep ? 'visible' : 'none');
});
if (map.getTerrain()) map.setTerrain(null);
}
}
document.querySelectorAll('#layers button').forEach(btn => {
btn.addEventListener('click', () => setMode(btn.dataset.mode));
});
</script>
</body>
</html>