1<!DOCTYPE html>
2<html lang='en'>
3
4<head>
5 <meta charset="utf-8" />
6 <script src="https://unpkg.com/maplibre-gl@5.6.0/dist/maplibre-gl.js"></script>
7 <link href="https://unpkg.com/maplibre-gl@5.6.0/dist/maplibre-gl.css" rel="stylesheet" />
8 <script src="https://unpkg.com/pmtiles@4.3.0/dist/pmtiles.js"></script>
9 <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
10 <style>
11 body {
12 margin: 0;
13 padding: 0;
14 }
15
16 #map {
17 position: absolute;
18 top: 0;
19 bottom: 0;
20 width: 100%;
21 }
22 </style>
23</head>
24
25<body>
26 <div id="map"></div>
27 <script type="text/javascript">
28
29 const protocol = new pmtiles.Protocol({ metadata: true, errorOnMissingTile: true });
30 maplibregl.addProtocol('mapterhorn', async (params, abortController) => {
31 const [z, x, y] = params.url.replace('mapterhorn://', '').split('/').map(Number);
32 const name = z <= 12 ? 'planet' : `6-${x >> (z - 6)}-${y >> (z - 6)}`;
33 const url = `pmtiles://https://s3.us-west-2.amazonaws.com/us-west-2.opendata.source.coop/mapterhorn/mapterhorn/${name}.pmtiles/${z}/${x}/${y}.webp`;
34 const response = await protocol.tile({ ...params, url }, abortController);
35 if (response['data'] === null) throw new Error(`Tile z=${z} x=${x} y=${y} not found.`);
36 return response;
37 });
38
39 const map = new maplibregl.Map({
40 container: 'map',
41 hash: 'map',
42 style: {
43 version: 8,
44 sources: {
45 hillshadeSource: {
46 type: 'raster-dem',
47 tiles: ['mapterhorn://{z}/{x}/{y}'],
48 encoding: 'terrarium',
49 tileSize: 512,
50 attribution: '<a href="https://mapterhorn.com/attribution">© Mapterhorn</a>'
51 },
52 },
53 layers: [
54 {
55 id: 'hillshade',
56 type: 'hillshade',
57 source: 'hillshadeSource',
58 },
59 ],
60 },
61 });
62 </script>
63</body>
64
65</html>