Animate a Symbol to Follow the Mouse in Maptoolkit Maps JS
Following the mouse with a symbol layer requires listening to the map’s mousemove event and calling setData on a GeoJSON source with the cursor’s geographic coordinates on each event. Because setData is lightweight for a single point, the update is fast enough to appear smooth at typical cursor speeds. Use this to build crosshair overlays, drag-to-place interactions, or custom cursor replacements that show geographic context.
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: [11.39085, 47.27574],
zoom: 12,
attributionControl: { compact: false }
});
map.addControl(new maptoolkit.NavigationControl(), 'top-right');
const dot = {
type: 'Feature',
geometry: { type: 'Point', coordinates: [0, 0] }
};
map.on('load', () => {
map.addSource('cursor', { type: 'geojson', data: dot });
map.addLayer({
id: 'cursor-circle',
type: 'circle',
source: 'cursor',
paint: {
'circle-radius': 12,
'circle-color': 'transparent',
'circle-stroke-width': 2,
'circle-stroke-color': '#ee8a65'
}
});
map.on('mousemove', (e) => {
dot.geometry.coordinates = [e.lngLat.lng, e.lngLat.lat];
map.getSource('cursor').setData(dot);
});
});<!DOCTYPE html>
<html lang="en">
<head>
<title>Animate a Symbol to Follow the Mouse - Maptoolkit Maps JS</title>
<meta property="og:description" content="Move a symbol layer to the mouse position on each mousemove event." />
<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%; cursor: none; }
</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: [11.39085, 47.27574],
zoom: 12,
attributionControl: { compact: false }
});
map.addControl(new maptoolkit.NavigationControl(), 'top-right');
const dot = {
type: 'Feature',
geometry: { type: 'Point', coordinates: [0, 0] }
};
map.on('load', () => {
map.addSource('cursor', { type: 'geojson', data: dot });
map.addLayer({
id: 'cursor-circle',
type: 'circle',
source: 'cursor',
paint: {
'circle-radius': 12,
'circle-color': 'transparent',
'circle-stroke-width': 2,
'circle-stroke-color': '#ee8a65'
}
});
map.on('mousemove', (e) => {
dot.geometry.coordinates = [e.lngLat.lng, e.lngLat.lat];
map.getSource('cursor').setData(dot);
});
});
</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
mousemove gives e.lngLat, and each event rebuilds the one-feature source through
setData, so the symbol tracks the cursor.
This is driven by events rather than frames, which is the right choice here: there is nothing
to draw between mouse movements, so a requestAnimationFrame loop would recompute an
unchanged position.
mousemove can fire more often than the screen refreshes. For anything heavier than moving one
point, buffer the latest position and apply it once per frame instead of on every event.
There is no touch equivalent, so a cursor-following symbol simply does not exist on a phone.
Next steps
A symbol tracking the cursor is most useful when it previews an action: where a marker would land, which point would be selected, what the click will do.
Snapping is what usually comes next, pulling the symbol to the nearest feature or road rather than following the cursor exactly, which turns a decoration into a placement tool.