If you've ever recorded a run, a bike ride, or a road trip, you have a GPX file somewhere. And if you've tried to turn it into a nice animated map for a video, a talk, or a blog post, you've probably found that raw GPS data is messier than it looks.
This guide covers the data side: getting a clean, light, privacy-safe track that animates smoothly. It's useful whether you animate with code (MapLibre, deck.gl) or a dedicated tool.

The goal: clean routes and regions that animate smoothly. Examples from the Mapimator showcase.
1. Get the GPX
Most apps let you export a GPX file:
- Strava: open an activity, use the "..." menu, then "Export GPX".
- Garmin Connect: activity, gear icon, "Export to GPX".
- Komoot: open a tour and download it as GPX.
- Google My Maps: export a layer as KML/KMZ (you can convert it to GeoJSON, see below).
GPX is just XML: tracks (trk) made of segments (trkseg) made of points (trkpt) with latitude, longitude, elevation, and time.
2. Convert to GeoJSON
Most web mapping libraries prefer GeoJSON. Two easy options:
Command line with GDAL:
ogr2ogr -f GeoJSON route.geojson ride.gpx tracks
The last argument is the layer name. GPX files expose tracks, track_points, routes, and waypoints layers. You usually want tracks.
In JavaScript with @tmcw/togeojson:
import { gpx } from '@tmcw/togeojson';
const xml = new DOMParser().parseFromString(gpxText, 'text/xml');
const geojson = gpx(xml);
3. Simplify the line
A one-hour ride recorded every second is 3,600 points. Animating every one of them is wasteful, and GPS jitter makes the line look shaky when you zoom in.
Simplification removes points that don't change the shape much:
npx mapshaper route.geojson -simplify 10% -o route-simple.geojson
Or with Turf.js:
import simplify from '@turf/simplify';
const simple = simplify(geojson, { tolerance: 0.0001, highQuality: true });
Tolerance is in degrees, so 0.0001 is roughly 10 m. Start there and adjust visually. For a continent-scale flight path you can go much higher; for a hiking trail at street level, keep it low.
4. Remove GPS noise
Common problems in raw tracks:
- Spikes: a single point that jumps hundreds of meters away. Filter points whose implied speed between neighbors is unrealistic for the activity.
- Stationary clusters: a cloud of points where you stopped for coffee. Simplification usually cleans these up, or you can drop consecutive points closer than a few meters apart.
-
Multiple segments: pausing the recording creates separate
trksegelements, which become a MultiLineString. Merge them if you want one continuous animated line.
5. Trim the start and end for privacy
This step is easy to forget. Most tracks begin and end at home. Before publishing a route anywhere, cut the first and last few hundred meters:
import length from '@turf/length';
import lineSliceAlong from '@turf/line-slice-along';
const km = length(line, { units: 'kilometers' });
const trimmed = lineSliceAlong(line, 0.5, km - 0.5, { units: 'kilometers' });
That removes 500 m from each end. Viewers still see the journey, without your front door.
6. Animate it
Now the line is ready. Your options:
Code it yourself. In MapLibre GL JS, the common approach is to add the line as a GeoJSON source and grow it over time by slicing it with lineSliceAlong on each animation frame, while moving the camera with map.easeTo or map.flyTo. Recording the output as a video file is the hard part: you'll need to capture frames at a fixed time step rather than in real time, or the result will stutter.
Use a tool. If you just need the video, a dedicated map animation tool saves a lot of work. I use Mapimator, which runs in the browser, imports GPX, KML, and GeoJSON directly, handles camera moves and route drawing, and exports MP4 for YouTube or vertical formats for Shorts and TikTok.
Either way, the cleaning steps above matter: a simplified, trimmed track animates more smoothly and looks more deliberate on screen.
Quick checklist
- [ ] Exported GPX from your app
- [ ] Converted to GeoJSON (
trackslayer) - [ ] Simplified to a sensible tolerance
- [ ] Removed spikes and merged segments
- [ ] Trimmed start and end for privacy
- [ ] Previewed at the zoom level you'll actually use
Clean data in, nice map out.

Top comments (0)