Skip to content

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 (raster or pmtiles)
  • visual state (visible, opacity, order)

You can initialize layers from config and then mutate them at runtime through the API.


Add and remove layers

ts
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):

ts
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:

ts
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:

sh
pmtiles inspect your-file.pmtiles

Update visibility and opacity

ts
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

ts
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

ts
const layers = map.getLayers();

This is useful for:

  • syncing external controls
  • persisting user preferences
  • generating shareable map state snapshots

Switch basemaps

ts
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 buildings

Recommended UX: expose this as a segmented control or dropdown in your host UI.


Built-in layer panel vs custom UI

Enable built-in controls:

ts
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.