Generate and add a missing icon to the map
Replicates the MapLibre example Generate and add a missing icon to the map. The points and their data-driven icon name (square-rgb-<r,g,b>) are YAML. No image by those names exists anywhere: the page answers MapLibre’s request for each one by painting a square in the colour the name spells out: through map.setMissingStyleImageResolver() on maplibre-gl 6, which MapLibre awaits before treating the icon as missing, and through the styleimagemissing event on 4 and 5. The layer starts hidden so the handler is listening before the first icon request.
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/generate-and-add-a-missing-icon-to-the-map/# The YAML half: three points whose icon NAME is computed from data# (`square-rgb-<r,g,b>`). No image by those names exists anywhere; the# page answers MapLibre's styleimagemissing event by painting one on# demand — see generate-and-add-a-missing-icon-to-the-map.js. The layer# starts hidden so the handler is listening before the first request.type: mapid: generate-and-add-a-missing-icon-to-the-mapconfig: center: [0, 0] zoom: 1 mapStyle: "https://demotiles.maplibre.org/style.json"layers: - id: points type: symbol visible: false source: type: geojson data: type: FeatureCollection features: - { type: Feature, geometry: { type: Point, coordinates: [0, 0] }, properties: { color: "255,0,0" } } - { type: Feature, geometry: { type: Point, coordinates: [50, 0] }, properties: { color: "255,209,28" } } - { type: Feature, geometry: { type: Point, coordinates: [-50, 0] }, properties: { color: "242,127,32" } } layout: icon-image: ["concat", "square-rgb-", ["get", "color"]]The JavaScript half
Section titled “The JavaScript half”// The JavaScript half: MapLibre asks the page for an image it doesn't have,// and the page paints it. The colour is parsed from the requested name// itself, so any `square-rgb-r,g,b` works.//// maplibre-gl 6 asks through map.setMissingStyleImageResolver(), which it// awaits before the icon counts as missing; an image added from the old// `styleimagemissing` event arrives too late there. maplibre-gl 4 and 5// only have the event, where a synchronous addImage() is in time.const mapEl = document.querySelector("ml-map");const prefix = "square-rgb-";
function paint(map, id) { if (!id.startsWith(prefix)) return; // not one this page can make const rgb = id.slice(prefix.length).split(",").map(Number); const width = 64; const data = new Uint8Array(width * width * 4); for (let i = 0; i < width * width; i++) { data.set([rgb[0], rgb[1], rgb[2], 255], i * 4); } map.addImage(id, { width, height: width, data });}
mapEl.mapReady().then((map) => { if (typeof map.setMissingStyleImageResolver === "function") { map.setMissingStyleImageResolver((id) => paint(map, id)); } else { map.on("styleimagemissing", ({ id }) => paint(map, id)); }
// Listening now — let the layer request its icons. mapEl.setLayerVisibility("points", true);});What to notice
Section titled “What to notice”- The handler must call
addImagesynchronously; MapLibre re-checks for the image as soon as the event returns. - maplibre-yaml’s own missing-image warning defers to page handlers: an image supplied this way is never reported as missing.