Markers and clusters
The shape
Section titled “The shape”The map takes plain objects. Map your records to them once:
map.markers = stores.map((store) => ({ id: store.id, // unique, string or number lng: store.longitude, // longitude first, always lat: store.latitude, label: store.openNow ? "Open" : undefined, // a short pill label, or nothing for a dot title: store.name, subtitle: store.address, badge: store.isNew ? "New" : undefined, image: store.photoUrl, // about 560 px wide, see Cards and popups href: `/stores/${store.slug}`, data: store, // the original record, typed through Marker<Store>}));| Field | Drawn as |
|---|---|
label set |
A pill with the text, for example $420, 4.8★, Open or 12 min. Ten characters at most. |
no label |
A dot in the theme’s accent colour. |
| several markers close together | A cluster bubble showing the count. Clicking it zooms in. |
The title, subtitle, badge, image, href and label fields fill the card that opens when a marker is clicked. See Cards and popups. Card photos are fetched ahead of the click for the markers nearest the centre, so serve them about 560 px wide, in WebP or AVIF, with long cache headers.
Updating
Section titled “Updating”Assign a new array. The map re-clusters (fast enough for tens of thousands of markers) and redraws on the next frame:
map.markers = map.markers.filter((marker) => marker.data.price < maxPrice);Changing the array keeps the camera, the open popup (if its marker is still there) and the selection.
Clustering
Section titled “Clustering”<instant-map cluster="60"></instant-map> <!-- merge more aggressively --><instant-map cluster="off"></instant-map> <!-- never merge -->Clusters are computed in world space at each whole zoom level. Panning never regroups them, and the first image the server renders has exactly the groups the live map draws. Pills and bubbles that would touch merge too, so markers never overlap.
Handle a cluster click yourself:
map.addEventListener("clusterclick", (event) => { event.preventDefault(); openSidebar(event.detail.cluster.markers);});How many markers?
Section titled “How many markers?”| Count | Notes |
|---|---|
| Up to 10,000 | Smooth on a mid-range phone. |
| 10,000–100,000 | Works. Clustering runs once per whole zoom level, so the first zoom-in pauses briefly. |
| More than 100,000 | Filter on the server first, by the visible bounds (moveend + map.bounds). |
The first image is unaffected by the count, because staticUrl() sends only the visible groups.