Add contour lines
Replicates the MapLibre example Add contour lines. The YAML declares the DEM, a hillshade over it, and contour line and label layers reading a vector source at contours://{z}/{x}/{y}. That protocol is the maplibre-contour plugin, registered by page JS on the maplibre module <ml-map> renders with. The plugin is built on the first contour tile request from the document’s own dem source, so the DEM is declared once.
The YAML half
Section titled “The YAML half”# yaml-language-server: $schema=https://docs.maplibre-yaml.org/schema/latest/map.schema.json# Gallery twin of https://maplibre.org/maplibre-gl-js/docs/examples/add-contour-lines/# The YAML half: the DEM, a hillshade over it, and contour line + label# layers reading a vector source served by the `contours://` protocol.# That protocol is the maplibre-contour plugin, registered by page JS on# the maplibre module <ml-map> renders with — see add-contour-lines.js.# The DEM is declared once, here: the plugin reads its URL and encoding# from this document's `dem` source.## NOTE for the live sweep: renders only with the page's protocol# registration; scripts/verify-docs-gallery.mjs drives it through the# hatch harness, which runs that JS.type: mapid: add-contour-linesconfig: center: [11.3229, 47.2738] zoom: 13 mapStyle: "https://demotiles.maplibre.org/style.json"sources: dem: type: raster-dem tiles: ["https://demotiles.maplibre.org/terrain-tiles/{z}/{x}/{y}.png"] encoding: mapbox tileSize: 256 maxzoom: 12 contours: type: vector tiles: ["contours://{z}/{x}/{y}"] maxzoom: 15layers: - id: hills type: hillshade source: dem paint: hillshade-exaggeration: 0.25 - id: contours type: line source: contours source-layer: contours paint: line-opacity: 0.5 # "major" contours have level 1, "minor" level 0 line-width: ["match", ["get", "level"], 1, 1, 0.5] - id: contour-text type: symbol source: contours source-layer: contours filter: [">", ["get", "level"], 0] layout: symbol-placement: line text-size: 10 text-field: ["concat", ["number-format", ["get", "ele"], {}], "'"] text-font: ["Noto Sans Bold"] paint: text-halo-color: white text-halo-width: 1The JavaScript half
Section titled “The JavaScript half”// The JavaScript half: a protocol plugin on the maplibre module <ml-map>// renders with. maplibre-contour turns DEM tiles into vector contour// tiles; registering `contours://` through @maplibre-yaml/core/maplibre// guarantees it lands on the same module the document's source requests// go through. The plugin is built lazily, on the first contour tile, from// the `dem` source the YAML declares — so the DEM lives in one place.import { addProtocol } from "@maplibre-yaml/core/maplibre";import mlcontour from "maplibre-contour";
const mapEl = document.querySelector("ml-map");
const contourOptions = { multiplier: 3.28084, // metres to feet overzoom: 1, thresholds: { // zoom: [minor, major] interval, in feet 11: [200, 1000], 12: [100, 500], 13: [100, 500], 14: [50, 200], 15: [20, 100], }, elevationKey: "ele", levelKey: "level", contourLayer: "contours",};
let demSource;function dem() { if (!demSource) { const spec = mapEl.getMap().getStyle().sources.dem; const template = spec.tiles[0]; demSource = new mlcontour.DemSource({ // The worker resolves URLs against nothing — make a site path absolute. url: template.startsWith("/") ? location.origin + template : template, encoding: spec.encoding ?? "mapbox", maxzoom: spec.maxzoom ?? 12, worker: true, // compute contours off the main thread }); } return demSource;}
addProtocol("contours", (request, abortController) => { const [z, x, y] = request.url.slice("contours://".length).split("/"); const url = dem() .contourProtocolUrl(contourOptions) .replace("{z}", z) .replace("{x}", x) .replace("{y}", y); return dem().contourProtocolV4({ ...request, url }, abortController);});What to notice
Section titled “What to notice”- Contour intervals per zoom live in the JS (
thresholds); the line styling — major lines thicker — stays in YAML, reading thelevelproperty the plugin writes. worker: truecomputes contours off the main thread.- Terrain: MapLibre demo tiles.