POIs & Content Search
WemapMap handles interaction and state for pinpoints already rendered in
the livemap style (vector-tile / GeoJSON features carrying a pinpoint
property). This is distinct from DomMarkerLayer, which places
your own runtime DOM pins.
POI interaction is owned by the map and is torn down with map.remove().
Clicks
onPoiClick resolves the full Pinpoint entity for the clicked feature. When
the pinpoint can't be resolved, no click event is fired and onPoiClickError is
notified instead.
map.onPoiClick(({ pinpoint, externalId, coordinates }) => {
console.log('clicked', pinpoint.id, pinpoint.name, externalId, coordinates.lat, coordinates.lng);
});
map.onPoiClickError(({ pinpointId, reason }) => {
console.warn('POI resolution failed', pinpointId, reason);
});
Highlight, select, filter
map.setPoiHighlighted([12, 34]);
map.setPoiSelected([56]);
map.filterPois([12, 34, 56]); // whitelist on default layers
map.showAllPois(); // clear the filter — show all again
map.hideAllPois(); // hide all pinpoints on default layers
filterPois([]) is equivalent to hideAllPois(). getPoiFilter() returns the
current whitelist (null = no filter, [] = all hidden), and
getPoiHighlighted() / getPoiSelected() read the current lists. All three
states are re-applied automatically across a style swap.
Highlighted, selected, and filtered are independent states — a selected POI and a set of highlighted search results coexist without interfering.
Automatic userflow
The calls above are the building blocks. To get the standard userflow without
wiring it yourself, opt in with the interaction option — every toggle is
off by default:
const map = new WemapMap({
container: 'map',
interaction: {
autoSelectOnClick: true, // click a POI → select it; click empty → clear
autoHighlightSearch: true, // map.search() highlights results + filters others
// centerOnSelect: true // (default) also ease the camera to the selected POI
},
});
autoSelectOnClick— clicking a stylesheet POI selects it (replacing any previous selection) and, unlesscenterOnSelect: false, eases the camera to it. Clicking the empty map background clears the selection. Your ownonPoiClicklisteners still fire on top of this.autoHighlightSearch— makesmap.search()apply its results to the map (highlight + filter) instead of only returning them.
You can always mix the auto-flow with the manual setPoiSelected /
setPoiHighlighted / filterPois calls.
Viewport pinpoints
To react to the pinpoints currently in view (for a synchronized list, say), subscribe to viewport changes. The callback fires on load, after the map stops moving, and on level change:
map.onViewportPinpointsChange(({ pinpoints, trigger }) => {
console.log('refreshed via', trigger, pinpoints.length);
});
Content search
map.search(query) searches the livemap's pinpoints within the current viewport
and level — no need to assemble the bounds/level query yourself:
const map = new WemapMap({
container: 'map',
interaction: { autoHighlightSearch: true },
});
const { items } = await map.search('museum');
// with autoHighlightSearch on: results are highlighted and every other
// pinpoint is filtered out of the default layers, in this one call.
map.clearSearch(); // clear the highlight + show all again (selection is kept)
Pass overrides via the second argument: map.search('museum', { limit: 20, tags, level }). When interaction.autoHighlightSearch is off, map.search() just
returns the results and leaves the map untouched — apply them yourself with
filterPois / setPoiHighlighted if you want.
For a custom search backend, skip map.search()
and drive the primitives directly — @wemap/core exposes the lower-level
pinpointManager.search:
import { boundsToDelta, core } from '@wemap/core';
const pinpointManager = core.createPinpointManager();
const { items } = await pinpointManager.search({
query: 'museum',
...boundsToDelta(map.getBounds()),
level: map.getLevel() ?? undefined,
});
map.setPoiHighlighted(items.map((p) => p.id));
map.filterPois(items.map((p) => p.id));
For the full API, see the Map API reference.