Markers & Clustering
DomMarkerLayer places runtime DOM pins (destinations, annotations, waypoints)
on the map. It is separate from stylesheet POIs and from
UserLocationLayer. You can also use it if your map doesn't have any POIs and you want to add them dynamically.
import { Coordinates } from '@wemap/geo';
import { DomMarkerLayer } from '@wemap/map';
const markers = new DomMarkerLayer(map, { levelVisibility: true });
markers.add({ id: 'dest', position: new Coordinates(48.85, 2.35, null, 1) });
markers.remove('dest');
add upserts by id (call it again with the same id to move / restyle a
marker). position accepts any LatLngLike — a Coordinates, a
{ lat, lng, level? } object, or a [lat, lng, level?] tuple — and an invalid
position throws. Pass a color / icon for the default pin, or your own
element for a fully custom marker. Individual marker clicks:
markers.on('click', ({ id, position }) => console.log('clicked', id, position));
Level visibility
By default (levelVisibility: true), a marker is hidden when its
position.level does not match map.getLevel(). When map.getLevel() is null
(outdoor / no floor selected), all markers stay visible. Pass
levelVisibility: false to always show every marker.
Clustering
Opt-in supercluster grouping, per
layer. Omit cluster for 1:1 markers (the default). Use a second, non-clustered
DomMarkerLayer for pins that must never cluster (origin, destination, …):
const pois = new DomMarkerLayer(map, {
cluster: {
enable: true,
radius: 80, // optional — livemap default
maxZoom: 18, // optional — defaults to the map's max zoom
zoomOnClick: true,
color: '#c0392b', // optional — overrides the themed default (--wemap-color-cluster)
},
});
pois.on('clusterclick', (event) => {
console.log(event.pointCount, event.markerIds);
// event.preventDefault(); // skip the default expansion zoom
});
pois.setClusterEnabled(false); // runtime toggle (no-op without constructor cluster config)
Cluster clicks zoom to the supercluster expansion level by default; individual
marker on('click') is unchanged. When levelVisibility is true, markers
hidden for the current floor don't participate in clustering, so clusters never
span floors.
Clean up
DomMarkerLayer is not destroyed by map.remove() by default — call
markers.destroy(), or cascade with map.remove({ layers: true }).
For the full API, see the DomMarkerLayer reference.