ef1d136a3e
- map-frontend: nginx serves MapLibre GL static app, proxies /tiles/ to pmtiles internally - pmtiles: remove host port binding (internal to npm-network only), update public-url - 5 themes: light, dark, grayscale, white, black
113 lines
3.6 KiB
HTML
113 lines
3.6 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Maps</title>
|
|
<link rel="stylesheet" href="https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.css">
|
|
<style>
|
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
html, body { height: 100%; }
|
|
#map { width: 100%; height: 100vh; }
|
|
|
|
#theme-control {
|
|
position: absolute;
|
|
top: 10px;
|
|
left: 10px;
|
|
z-index: 1;
|
|
}
|
|
|
|
#theme-control select {
|
|
appearance: none;
|
|
background: #fff;
|
|
border: 1px solid rgba(0,0,0,0.2);
|
|
border-radius: 4px;
|
|
box-shadow: 0 1px 4px rgba(0,0,0,0.15);
|
|
cursor: pointer;
|
|
font-family: system-ui, sans-serif;
|
|
font-size: 13px;
|
|
padding: 6px 28px 6px 10px;
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23666'/%3E%3C/svg%3E");
|
|
background-repeat: no-repeat;
|
|
background-position: right 10px center;
|
|
}
|
|
|
|
#theme-control select.dark {
|
|
background-color: #1a1a1a;
|
|
color: #eee;
|
|
border-color: rgba(255,255,255,0.2);
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23aaa'/%3E%3C/svg%3E");
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="map"></div>
|
|
<div id="theme-control">
|
|
<select id="theme">
|
|
<option value="light">Light</option>
|
|
<option value="dark">Dark</option>
|
|
<option value="grayscale">Grayscale</option>
|
|
<option value="white">White</option>
|
|
<option value="black">Black</option>
|
|
</select>
|
|
</div>
|
|
|
|
<script src="https://unpkg.com/maplibre-gl@4/dist/maplibre-gl.js"></script>
|
|
<script type="module">
|
|
import { layers, namedFlavor } from 'https://esm.sh/@protomaps/basemaps@4';
|
|
|
|
const TILESET = 'north-america';
|
|
|
|
function buildStyle(theme) {
|
|
return {
|
|
version: 8,
|
|
glyphs: 'https://protomaps.github.io/basemaps-assets/fonts/{fontstack}/{range}.pbf',
|
|
sprite: `https://protomaps.github.io/basemaps-assets/sprites/v4/${theme}`,
|
|
sources: {
|
|
protomaps: {
|
|
type: 'vector',
|
|
tiles: [`${window.location.origin}/tiles/${TILESET}/{z}/{x}/{y}.mvt`],
|
|
minzoom: 0,
|
|
maxzoom: 15,
|
|
attribution: '© <a href="https://openstreetmap.org">OpenStreetMap</a>'
|
|
}
|
|
},
|
|
layers: layers('protomaps', namedFlavor(theme), { lang: 'en' })
|
|
};
|
|
}
|
|
|
|
const map = new maplibregl.Map({
|
|
container: 'map',
|
|
style: buildStyle('light'),
|
|
center: [-98, 39],
|
|
zoom: 4
|
|
});
|
|
|
|
map.addControl(new maplibregl.NavigationControl(), 'top-right');
|
|
map.addControl(new maplibregl.ScaleControl(), 'bottom-left');
|
|
map.addControl(new maplibregl.FullscreenControl(), 'top-right');
|
|
map.addControl(new maplibregl.GeolocateControl({
|
|
positionOptions: { enableHighAccuracy: true },
|
|
trackUserLocation: true
|
|
}), 'top-right');
|
|
|
|
const themeSelect = document.getElementById('theme');
|
|
|
|
themeSelect.addEventListener('change', e => {
|
|
const theme = e.target.value;
|
|
const { lng, lat } = map.getCenter();
|
|
const zoom = map.getZoom();
|
|
const bearing = map.getBearing();
|
|
const pitch = map.getPitch();
|
|
|
|
themeSelect.className = (theme === 'dark' || theme === 'black') ? 'dark' : '';
|
|
|
|
map.setStyle(buildStyle(theme));
|
|
map.once('styledata', () => {
|
|
map.jumpTo({ center: [lng, lat], zoom, bearing, pitch });
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|