Scenes, bookmarks and tours
A scene is the whole state of the map as one plain object: where the camera is, what is shown, what the slicers and filters are set to, what is selected and which basemap is active. Capture it, keep it wherever you like, and put the map back exactly there later.
It is the same state one of the author's bookmarks holds, plus your filters, the selection and the basemap.
Capture and restore
const scene = await map.captureScene();
localStorage.setItem("last-view", JSON.stringify(scene));
// ... later, even after the map has been re-published
const { skipped } = await map.applyScene({ scene: JSON.parse(localStorage.getItem("last-view")), animate: true });
// EmbedScene
{
v: 1,
camera: { center: [lng, lat], zoom, bearing, pitch },
visibility: { layers: { ... }, labels, hillshade, terminator, features: { ... }, visuals: { ... } },
slicers: { "slicer-region": { ... } },
filters: { region: ["EMEA"] },
selection: { assets: ["41B"] },
basemapId: "slate"
}
Scenes survive a re-publish. If the author has since removed a layer or a slicer, that part of the scene is skipped and named in skipped (for example "layer:old-depots"); everything else is restored. Nothing fails.
Capture only what you want to carry:
const viewOnly = await map.captureScene({ include: ["camera", "visibility"] });
Return everything to what the author published with map.resetScene().
Start from a scene
Pass a scene at mount and the reader never sees the default view first:
embed(el, { publishId, scene: JSON.parse(localStorage.getItem("last-view")) });
Share a scene as a link
sceneToUrl turns a scene into a link that opens the map exactly there - no code needed on the page that opens it:
const { sceneToUrl } = IconMapEmbed;
const scene = await map.captureScene();
const link = sceneToUrl("https://embed.iconmap.ai/v/pub_...", { scene });
The scene rides the URL fragment (#s=...), which browsers never send to a server, so it does not appear in access logs. See Deep links.
If you would rather store an opaque string than an object, ask for one - applyScene takes either:
const { state } = await map.captureScene({ opaque: true });
await map.applyScene({ scene: { state } });
Bookmarks
Bookmarks are views the map's author saved. List them and apply one - it goes through the same path as the map's own bookmarks bar, so the two never disagree.
The author decides whether bookmarks are offered: getBookmarks() returns an empty list unless Show a bookmarks control in the viewer was ticked when the map was published.
const bookmarks = await map.getBookmarks(); // [{ id, name, description? }]
await map.applyBookmark({ bookmarkId: bookmarks[0].id, animate: true });
map.on("bookmarkApplied", ({ bookmarkId }) => highlightMyTab(bookmarkId));
Build your own bookmark navigation and hide the map's:
await map.setChrome({ bookmarksBar: false });
To open on a bookmark, pass bookmarkId at mount.
Tours
A tour is a sequence of views the author recorded.
const tours = await map.getTours(); // [{ id, name }]
await map.playTour({ tourId: tours[0].id });
await map.stopTour();
map.on("tourStateChanged", ({ tourId, state }) => { /* "started" | "keyframe" | "ended" */ });
While a tour plays, viewChanged events carry reason: "tour", so a view-syncing handler that only acts on "user" stays quiet.
Which to use
| You want to | Use |
|---|---|
| Remember where each user left the map | captureScene on viewChanged (reason user), scene at mount |
| Offer named views the author designed | getBookmarks + applyBookmark |
| "Copy link to this view" | captureScene + sceneToUrl |
| Open a map in a given state from an email or a report | A deep link |
| Move only the camera | setView / flyTo - a scene is more than you need |