Documentation menu
Example
GeoJSON lines and polygons
Your own zones and paths from one GeoJSON source: a fill and an outline for the polygons, a line for the paths, split by geometry type. The layers sit beneath the labels, so street names stay readable over your shapes.
ts
import { createMap } from "@mapmap/maps";
import "maplibre-gl/dist/maplibre-gl.css";
const map = createMap({
container: "map",
apiKey: "snk_...",
attributionPosition: "bottom-left",
center: [-0.098, 51.505],
zoom: 13.2,
});
await map.whenReady();
// One source, any mix of geometries. data also takes a URL to a .geojson.
map.addPersistentSource("my-shapes", {
type: "geojson",
data: {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: { name: "Delivery zone A" },
geometry: {
type: "Polygon",
coordinates: [[
[-0.112, 51.498], [-0.084, 51.498], [-0.084, 51.511],
[-0.112, 51.511], [-0.112, 51.498],
]],
},
},
{
type: "Feature",
properties: { name: "Riverside path" },
geometry: {
type: "LineString",
coordinates: [
[-0.1195, 51.5033], [-0.1080, 51.5075], [-0.0990, 51.5080],
[-0.0870, 51.5070], [-0.0760, 51.5055],
],
},
},
],
},
});
// slot "middle": above the roads, below every label. Persistent layers come
// back after every map.setStyle(...), at the same slot.
map.addPersistentLayer({
id: "my-zones-fill",
type: "fill",
source: "my-shapes",
filter: ["==", ["geometry-type"], "Polygon"],
paint: { "fill-color": "#1a6bff", "fill-opacity": 0.16 },
}, { slot: "middle" });
map.addPersistentLayer({
id: "my-zones-outline",
type: "line",
source: "my-shapes",
filter: ["==", ["geometry-type"], "Polygon"],
paint: { "line-color": "#1a6bff", "line-width": 1.5 },
}, { slot: "middle" });
map.addPersistentLayer({
id: "my-paths",
type: "line",
source: "my-shapes",
filter: ["==", ["geometry-type"], "LineString"],
layout: { "line-cap": "round", "line-join": "round" },
paint: { "line-color": "#e07b39", "line-width": 4 },
}, { slot: "middle" });Worth knowing
- The slot says where your layer sits: "bottom" beneath the roads and buildings, "middle" above the roads and below every label, "top" above POI labels and below place names. The full table is under insertion points on /docs/custom-data.
- addPersistentSource and addPersistentLayer survive map.setStyle(...): a theme swap re-adds them at their slot. A layer added through map.map directly is dropped on setStyle; insert it with map.map.addLayer(layer, map.slot("middle")) and re-add it in a style.load handler.