Layers and Basemaps
This guide covers day-to-day layer operations in real applications.
Layer model at a glance
Each layer has:
- an identity (
id) - a display label (
name) - a source type (
rasterorpmtiles) - visual state (
visible,opacity,order)
You can initialize layers from config and then mutate them at runtime through the API.
Add and remove layers
map.addLayer({
id: "contours",
name: "Contours",
type: "pmtiles",
url: "https://example.com/contours.pmtiles",
visible: true,
opacity: 1,
order: 4,
});
map.removeLayer("contours");Use stable IDs that match your domain concepts (dem, contours, backscatter) so host UI code stays readable.
PMTiles contour layers
PMTiles vector layers (type: "pmtiles") are rendered as three MapLibre sub-layers: secondary contour lines, master contour lines, and elevation labels. The library needs to know which feature property holds the elevation value and how to classify contours as master or secondary. These are configured via the style object.
Defaults work for standard sources (property named elev, every 5th interval is master, labels in inches):
map.addLayer({
id: "contours",
name: "Contours",
type: "pmtiles",
url: "https://example.com/contours.pmtiles",
sourceLayer: "contours",
visible: true,
opacity: 1,
order: 4,
});For a custom source — specify elevProperty, masterInterval, and labelSuffix to match the data:
map.addLayer({
id: "chicago_contours",
name: "Chicago Harbor Lock - Contours",
type: "pmtiles",
url: "https://storage.mapprism.com/demo/chicago-harbor-lock/dist/Chicago Harbor Lock - Contours.pmtiles",
sourceLayer: "contours",
visible: true,
opacity: 1,
order: 4,
style: {
elevProperty: "depth", // property name in the vector features
masterInterval: 5, // promote every 5th contour to master
labelSuffix: " ft", // unit suffix shown in labels
},
});Use a tool like the pmtiles CLI to inspect a file's internal layer names and property names:
pmtiles inspect your-file.pmtilesUpdate visibility and opacity
map.updateLayer("xyz_dem", { visible: false });
map.updateLayer("xyz_hillshade", { opacity: 0.4 });Common pattern: keep analysis layers loaded but hidden, then toggle visibility instead of removing/re-adding.
Reorder stack with order
map.updateLayer("xyz_hillshade", { order: 10 });Higher order values draw later (on top).
Use this for quick presentation presets such as:
- imagery-first mode
- contours-on-top mode
- terrain-analysis mode
Read current state
const layers = map.getLayers();This is useful for:
- syncing external controls
- persisting user preferences
- generating shareable map state snapshots
Switch basemaps
map.setBasemap("basemap"); // CartoDB Positron analytical map
map.setBasemap("satellite"); // satellite imagery, labels on top
map.setBasemap("hybrid"); // satellite imagery, road network + labels on top
map.setBasemap("basemap-2.5d"); // CartoDB Positron + extruded buildings
map.setBasemap("hybrid-2.5d"); // satellite imagery + road network + extruded buildingsRecommended UX: expose this as a segmented control or dropdown in your host UI.
Built-in layer panel vs custom UI
Enable built-in controls:
const config = {
map2d: {
layerPanel: true,
},
};- Built-in panel is best for fast integration and operator tooling.
- Custom UI is best when you need strict design-system consistency.
Both options use the same underlying runtime API.