Fly to a location
Move the camera from your own buttons. flyTo animates along a curve, fitBounds frames a box, and fitLayer frames a layer's data without you knowing any coordinates. The readout on the right is driven by the viewChanged event - try dragging the map and watch the reason change from command to user.
What to notice
- Coordinates are always
[longitude, latitude]. fitLayerframes the data as currently filtered, so it pairs naturally with slicers and filters.fitBoundsandfitLayerkeep the camera's pitch unless you say where to land: passpitch: 0, bearing: 0for a flat, north-up frame.viewChangedcarries areason, which is what lets a two-way sync ignore the echo of its own commands.
The code
The complete page. Swap in your own publish id, and ask the map's author to add your site to its allowed origins.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Fly to a location - Icon Map Embed API</title>
<link rel="stylesheet" href="https://www.icon-map.com/embed-examples/examples.css"> <!-- demo styling only -->
</head>
<body>
<div class="ex-bar">
<span class="ex-label">Fly to</span>
<button data-city="tokyo">Tokyo</button>
<button data-city="london">London</button>
<button data-city="lagos">Lagos</button>
<button data-city="saopaulo">Sao Paulo</button>
<button id="europe">Frame Europe</button>
<button id="cities">Frame every city</button>
<button id="home">Home</button>
<span class="ex-spacer"></span>
<pre class="ex-readout" id="readout"></pre>
</div>
<div class="ex-main"><div id="map"></div></div>
<script src="https://www.icon-map.com/js/iconmap-embed/2/iconmap-embed.umd.min.js"></script>
<script>
const el = document.getElementById("map");
const map = IconMapEmbed.embed(el, {
publishId: "pub_...",
// The map is a globe: let this page's own background show in the space around it.
background: "transparent",
// Start calm: hide the map's own panels and cards for this demo.
chrome: { legend: false, layerControl: false, bookmarksBar: false, tourTransport: false },
visibility: { visuals: { "chart-continent": false, "slicer-continent": false, "slicer-size": false, "slicer-capital": false } },
events: ["viewChanged"],
});
map.ready.catch((error) => console.error(error.code, error.message));
const places = {
tokyo: { center: [139.75, 35.69], zoom: 7.5, pitch: 40, bearing: -20 },
london: { center: [-0.12, 51.5], zoom: 7.5, pitch: 30, bearing: 15 },
lagos: { center: [3.39, 6.45], zoom: 7, pitch: 35, bearing: 0 },
saopaulo: { center: [-46.63, -23.56], zoom: 7.5, pitch: 40, bearing: 25 },
};
// flyTo animates along a curve; setView jumps (or eases with animate: true).
for (const button of document.querySelectorAll("[data-city]")) {
button.onclick = () => map.flyTo({ ...places[button.dataset.city], durationMs: 3500 });
}
// fitBounds frames a box: [[west, south], [east, north]]. pitch and bearing are where the camera
// LANDS - without them a frame keeps the tilt of the flight before it.
document.getElementById("europe").onclick = () =>
map.fitBounds({ bounds: [[-11, 35], [40, 71]], padding: 30, pitch: 0, bearing: 0 });
// fitLayer frames a layer's data as currently filtered - no coordinates needed.
document.getElementById("cities").onclick = () =>
map.fitLayer({ layerId: "cities", padding: 20, pitch: 0, bearing: 0 });
document.getElementById("home").onclick = () =>
map.setView({ center: [18, 22], zoom: 2.05, pitch: 0, bearing: 0, animate: true });
// viewChanged fires when the camera settles. `reason` says who moved it.
map.on("viewChanged", (view) => {
document.getElementById("readout").textContent =
`${view.center[0].toFixed(2)}, ${view.center[1].toFixed(2)} z${view.zoom.toFixed(1)} ` +
`pitch ${Math.round(view.pitch)} (${view.reason})`;
});
</script>
</body>
</html>