Skip to content
Documentation menu
docs / examples / interactions
Example

Click and hover on basemap features

React to clicks and hovers on the basemap's own POIs, place names and buildings with addInteraction and a named featureset, shaped like Mapbox's. Handlers resolve against the live style, so they keep working after a theme swap.

ts
import { createMap } from "@mapmap/maps";

const map = createMap({
  container: "map",
  apiKey: "snk_...",
  attributionPosition: "bottom-left",
  center: [-0.1276, 51.5072],
  zoom: 15.5,
});
await map.whenReady();

const info = document.querySelector("#info")!;

// Click a POI label. Returning true stops the click reaching anything
// below it, including the map-level interaction further down.
map.addInteraction("poi-click", {
  type: "click",
  target: { featuresetId: "poi" },
  handler: ({ feature }) => {
    info.textContent = String(feature?.properties.name ?? "");
    return true;
  },
});

// A pointer cursor over POIs and place names.
for (const featuresetId of ["poi", "place-labels"] as const) {
  map.addInteraction(featuresetId + "-enter", {
    type: "mouseenter",
    target: { featuresetId },
    handler: () => { map.map.getCanvas().style.cursor = "pointer"; },
  });
  map.addInteraction(featuresetId + "-leave", {
    type: "mouseleave",
    target: { featuresetId },
    handler: () => { map.map.getCanvas().style.cursor = ""; },
  });
}

// No target: the map itself, for a click that hit nothing above.
map.addInteraction("map-click", {
  type: "click",
  handler: ({ lngLat }) => {
    info.textContent = lngLat.lat.toFixed(5) + ", " + lngLat.lng.toFixed(5);
  },
});

map.setStyle("dark");   // the interactions stay

Worth knowing

  • Featuresets: poi covers poi-labels; place-labels covers place, city and country labels; buildings covers building and building-3d. A layer the live style does not carry is skipped, so a theme without 3D buildings still matches the flat ones.
  • buildings is best effort: the tiles merge neighbouring footprints of the same height into one feature, so feature state set on a building lights up its whole merged group. The clicked geometry is still right. poi and place-labels are exact, one id per label.
  • Later interactions get events first. A handler returning true stops click and mousemove there; mouseenter and mouseleave always reach every interaction listening.
  • For your own data, DataLayer wires hover, selection and popups itself: see the hover highlight example.