Update a Feature in Realtime in Maptoolkit Maps JS
Real-time feature updates in Maptoolkit Maps JS work by calling source.setData with a new GeoJSON FeatureCollection on each tick of a timer or incoming data event. The map renderer diffs the new data against the previous state and redraws only what changed. Use this to track a moving vehicle, show a live sensor reading, or reflect any backend data change on the map without reloading the page.
const API_KEY = 'YOUR_API_KEY';
const map = new maptoolkit.Map({
container: 'map',
apiKey: API_KEY,
style: `https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=${API_KEY}`,
center: [12.0, 47.5],
zoom: 7,
attributionControl: { compact: false }
});
map.addControl(new maptoolkit.NavigationControl(), 'top-right');
const cities = [
[11.39085, 47.27574],
[13.0550, 47.8095],
[16.3738, 48.2082],
[15.4395, 47.0707],
[11.576, 48.1374],
[8.5417, 47.3769]
];
let cityIndex = 0;
const dot = {
type: 'Feature',
geometry: { type: 'Point', coordinates: cities[0] }
};
map.on('load', () => {
map.addSource('dot', { type: 'geojson', data: dot });
map.addLayer({
id: 'dot',
type: 'circle',
source: 'dot',
paint: { 'circle-radius': 14, 'circle-color': '#ee8a65', 'circle-stroke-width': 2, 'circle-stroke-color': '#fff' }
});
setInterval(() => {
cityIndex = (cityIndex + 1) % cities.length;
dot.geometry.coordinates = cities[cityIndex];
map.getSource('dot').setData(dot);
}, 1500);
});<!DOCTYPE html>
<html lang="en">
<head>
<title>Update a Feature in Realtime - Maptoolkit Maps JS</title>
<meta property="og:description" content="Update a GeoJSON feature's position in real time by calling setData on a source." />
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@maptoolkit/maps@11.0.0-beta.3/dist/maptoolkit.css" />
<style>
html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
#map { width: 100%; height: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
const API_KEY = 'YOUR_API_KEY';
const map = new maptoolkit.Map({
container: 'map',
apiKey: API_KEY,
style: `https://styles.maptoolkit.net/maptoolkit/maptoolkit.summer.json?api_key=${API_KEY}`,
center: [12.0, 47.5],
zoom: 7,
attributionControl: { compact: false }
});
map.addControl(new maptoolkit.NavigationControl(), 'top-right');
const cities = [
[11.39085, 47.27574],
[13.0550, 47.8095],
[16.3738, 48.2082],
[15.4395, 47.0707],
[11.576, 48.1374],
[8.5417, 47.3769]
];
let cityIndex = 0;
const dot = {
type: 'Feature',
geometry: { type: 'Point', coordinates: cities[0] }
};
map.on('load', () => {
map.addSource('dot', { type: 'geojson', data: dot });
map.addLayer({
id: 'dot',
type: 'circle',
source: 'dot',
paint: { 'circle-radius': 14, 'circle-color': '#ee8a65', 'circle-stroke-width': 2, 'circle-stroke-color': '#fff' }
});
setInterval(() => {
cityIndex = (cityIndex + 1) % cities.length;
dot.geometry.coordinates = cities[cityIndex];
map.getSource('dot').setData(dot);
}, 1500);
});
</script>
</body>
</html>Use the prompt below with any LLM to get the same result. Make sure the Maptoolkit MCP server is connected first — check out AI Integration & MCP to get started.
How it works
A GeoJSON source has no incremental update path. You replace the whole payload
with setData and the renderer diffs it, so there is no “move one feature” call to look
for.
Here a single point feature is rebuilt with new coordinates on each tick and pushed through
setData. The layer never changes, only the data behind it.
Calling setData on a timer makes the feature jump between positions. Smooth movement
means interpolating between the old and new coordinates over several frames with
requestAnimationFrame and calling setData on each one, which is a different trade-off:
smoother, and more updates.
map.getSource(id) returns the source object, and setData lives on that rather than on the
map.
Next steps
Interpolating between updates is what makes a tracked feature look alive rather than teleporting, and it is the single biggest improvement available here.
After that, the questions are about state rather than rendering: what happens when a feature stops reporting, how stale is too stale, and whether a vehicle that has not moved in ten minutes should look different from one that is running. Those decisions are what separate a tracking map from a moving dot.