Skip to content

Commit 2b9bcde

Browse files
committed
OFM Topo: switch tile source, add bicycle layer, refine MTB styling
Update the outdoors example with multiple improvements: - Switch terrain tile source from S3 terrarium to mapterhorn (WebP), bump tileSize to 512 and maxzoom to 15 - Restructure MTB trail layer with beforeId positioning and flat opacity - Add bicycle-access layer for tracks tagged with bicycle=* - Refine path/track widths and hide path overlay on mtb_scale features - Clean up comments and add attribution links Files changed: - public/examples/outdoors/index.html
1 parent 526856a commit 2b9bcde

1 file changed

Lines changed: 107 additions & 58 deletions

File tree

public/examples/outdoors/index.html

Lines changed: 107 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66

77
<title>OFM Topo</title>
88

9+
<!-- 🙇 https://maplibre.org/ -->
910
<script src="https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.js"></script>
1011
<link
1112
href="https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.css"
1213
rel="stylesheet"
1314
/>
15+
16+
<!-- 🙇 https://github.com/onthegomap/maplibre-contour -->
1417
<script src="https://cdn.jsdelivr.net/npm/maplibre-contour@latest/dist/index.min.js"></script>
1518
<link rel="icon" href="data:," />
1619
<style>
@@ -25,33 +28,33 @@
2528
<body>
2629
<div id="map"></div>
2730
<script>
28-
const TERRARIUM_URL =
29-
"https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png";
31+
// 🙇 https://registry.opendata.aws/terrain-tiles/
32+
// const TERRARIUM_URL = "https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png";
33+
34+
// 🙇 https://github.com/mapterhorn/mapterhorn
35+
const TERRARIUM_URL = "https://tiles.mapterhorn.com/{z}/{x}/{y}.webp";
3036

3137
const terrainSource = {
3238
type: "raster-dem",
3339
tiles: [TERRARIUM_URL],
3440
encoding: "terrarium",
35-
tileSize: 256,
36-
maxzoom: 14,
41+
tileSize: 512,
42+
maxzoom: 15,
3743
};
3844

3945
const map = new maplibregl.Map({
4046
container: "map",
41-
style: "https://tiles.openfreemap.org/styles/liberty",
4247

43-
// Skovhuggeren mtb_scale example:
44-
// center: [10.52302507, 55.0952585],
48+
// 🙇 https://openfreemap.org/
49+
style: "https://tiles.openfreemap.org/styles/liberty",
4550

46-
// Cumberland mtb:scale:imba example:
51+
// Cumberland mtb:scale:imba example... not supported
4752
center: [-125.022417, 49.607406],
4853

4954
// Pove del Grappa 45.821142,11.7373742
50-
// center: [11.7373742, 45.824042],
55+
//center: [11.7373742, 45.824042],
5156

5257
zoom: 12,
53-
pitch: 0,
54-
bearing: 0,
5558
});
5659

5760
map.on("style.load", () => {
@@ -73,13 +76,12 @@
7376
});
7477

7578
// === Contours ===
79+
7680
const demSource = new mlcontour.DemSource({
7781
url: TERRARIUM_URL,
7882
encoding: "terrarium",
7983
maxzoom: 13,
8084
worker: true,
81-
cacheSize: 100,
82-
timeoutMs: 10000,
8385
});
8486
demSource.setupMaplibre(maplibregl);
8587
map.addSource("contour-source", {
@@ -161,52 +163,92 @@
161163
},
162164
});
163165

164-
// MTB trail highlighting (openfreemap/openmaptiles mtb_scale)
165-
map.addLayer({
166-
id: "mtb_scale-casing",
167-
type: "line",
168-
metadata: {
169-
"mapbox:group": "1444849345966.4436",
170-
},
171-
source: "openmaptiles",
172-
"source-layer": "transportation",
173-
filter: [
174-
"all",
175-
["==", "$type", "LineString"],
176-
["!=", "brunnel", "tunnel"],
177-
["has", "mtb_scale"],
178-
],
179-
layout: {
180-
"line-cap": "round",
181-
"line-join": "round",
182-
},
183-
paint: {
184-
"line-color": [
185-
"match",
186-
["get", "mtb_scale"],
187-
"1",
188-
"blue",
189-
"2",
190-
"red",
191-
"black",
166+
// === MTB trail example (using mtb_scale) ===
167+
// Placed above road layers but below POI icons/labels via beforeId (2nd arg)
168+
// https://github.com/hyperknot/openfreemap/issues/31#issuecomment-4649028862
169+
// Not exhaustive, e.g. mtb:scale=imba is not included
170+
// https://wiki.openstreetmap.org/wiki/Key:mtb:scale:imba
171+
//
172+
// Activity layers use minzoom: 0 + setLayerZoomRange(0, 22) so they render
173+
// at every zoom where the tag data exists in the tile — no artificial
174+
// zoom gating. If the tile has it, we show it.
175+
map.addLayer(
176+
{
177+
id: "mtb_scale-casing",
178+
type: "line",
179+
metadata: {
180+
"mapbox:group": "1444849345966.4436",
181+
},
182+
source: "openmaptiles",
183+
"source-layer": "transportation",
184+
minzoom: 0, // no minimum zoom — data availability determines visibility
185+
filter: [
186+
"all",
187+
["==", "$type", "LineString"],
188+
["!=", "brunnel", "tunnel"],
189+
["has", "mtb_scale"],
192190
],
193-
"line-opacity": {
194-
stops: [
195-
[13, 0],
196-
[16, 1],
197-
],
191+
layout: {
192+
"line-cap": "round",
193+
"line-join": "round",
198194
},
199-
"line-width": {
200-
base: 1.2,
201-
stops: [
202-
[12, 0.5],
203-
[16, 3],
195+
paint: {
196+
"line-color": [
197+
"match",
198+
["get", "mtb_scale"],
199+
"1",
200+
"blue",
201+
"2",
202+
"red",
203+
"black",
204204
],
205+
"line-opacity": 0.8,
206+
"line-width": {
207+
base: 1.2,
208+
stops: [
209+
[12, 0.5],
210+
[16, 3],
211+
],
212+
},
205213
},
206214
},
207-
});
215+
"poi_r20",
216+
);
217+
map.setLayerZoomRange("mtb_scale-casing", 0, 22); // visible at all zooms — tile data decides
218+
219+
// === Bicycle access ===
220+
// A single bold grey line for any trail tagged with bicycle=*
221+
// (designated, yes, permissive, etc.). Roads excluded — bicycle
222+
// tags are common on roads too, but this example spotlights trails.
223+
// Excludes path-class features (already styled by road_path_pedestrian)
224+
// so only tracks get the green overlay.
225+
// https://wiki.openstreetmap.org/wiki/Key:bicycle
226+
map.addLayer(
227+
{
228+
id: "bicycle-access",
229+
type: "line",
230+
source: "openmaptiles",
231+
"source-layer": "transportation",
232+
minzoom: 0, // no minimum zoom — data availability determines visibility
233+
filter: [
234+
"all",
235+
["==", "$type", "LineString"],
236+
["!=", "brunnel", "tunnel"],
237+
["has", "bicycle"],
238+
["in", "class", "track"],
239+
],
240+
paint: {
241+
"line-color": "#6c6b6a",
242+
"line-opacity": 0.7,
243+
"line-width": 2,
244+
},
245+
},
246+
"poi_r20",
247+
);
248+
map.setLayerZoomRange("bicycle-access", 0, 22);
208249

209250
// === Path/track highlighting ===
251+
210252
// Philosophy: if the tile has trail data, display it. No zoom filtering,
211253
// no fade-in — loud and proud at all zoom levels.
212254
//
@@ -223,20 +265,27 @@
223265
["exponential", 1.2],
224266
["zoom"],
225267
12,
226-
1.5,
268+
1,
227269
14,
228-
3,
270+
2,
229271
20,
230-
12,
272+
8,
273+
]);
274+
275+
// Hide Path/track highlighting on features with mtb_scale
276+
map.setPaintProperty("road_path_pedestrian", "line-opacity", [
277+
"case",
278+
["has", "mtb_scale"],
279+
0,
280+
1,
231281
]);
232282
}
233283

234-
// Trail name labels — same philosophy: show them wherever data exists
284+
// Path name labels — style the base highway-name-path layer.
285+
// Uses the transportation_name source-layer which has 'name'
235286
if (map.getLayer("highway-name-path")) {
236287
map.setLayerZoomRange("highway-name-path", 0, 22);
237288
map.setPaintProperty("highway-name-path", "text-color", "#c05a2a");
238-
map.setPaintProperty("highway-name-path", "text-halo-color", "#ffffff");
239-
map.setPaintProperty("highway-name-path", "text-halo-width", 1.5);
240289
}
241290

242291
// Note: tunnel/bridge path variants, poi, building extrusions etc.

0 commit comments

Comments
 (0)