We’ve been playing with mapping GoPro video, most recently using some of Bobby’s biking footage and overlaying it with his Strava GPX track. We synced up the video track using MapBox.js that embeds a video in a marker’s popup and moves it along a route. Similar to the Marker Movement example, a popup with the video in an iframe is bound to the marker’s track so it can go along for the ride. We have similar examples on the new MapBox.js examples page and I also pulled together this tutorial, starting with an initial route and marker from your GPX data, and then show how to set a marker along the vertices of a route to animate it along a line and then showing how to bind a popup to a marker so the video traverses the route.

Setting up the map

We start by setting up our basic map, position, and zoom level. The popup is also set to stay open in case it is clicked to close.

var map = L.mapbox.map('map', 'mapbox.streets', {
  closePopupOnClick:false
}).setView([38.95, -77.01459], 12);

Loading the JSON

Tracks recorded by Strava can be easily exported as a GPX file and loaded into geojson.io for conversion into a GeoJSON format that’s easy for MapBox.js to consume.

GeoJSON

There are other ways to include GeoJSON, but for this example, we’re including it as the variable ride from an external JavaScript file <script src='ridelapse.js'></script> in the header.

var ride = {
  type: 'FeatureCollection',
  features: [{
    type: 'Feature',
    id: 0,
    properties: {
      name: 'Team MapBox'
    },
    geometry: {
      type: 'LineString',
      coordinates: [ [ -77.012451, 38.912549 ],

a snippet of ridelapse.js

Next, we make a style for the line then add the ride variable into our example as the GeoJSON. A marker is also added to indicate the current position starting at the beginning coordinates of the ride.

function style(feature) {
  return {
    weight: 7,
    opacity: 1,
    color: '#0d8709',
    opacity: 0.7
  };
}

var line = L.geoJson(ride, {
  style: style
}).addTo(map);

var marker = L.marker([0, 0], {
  icon: L.mapbox.marker.icon({
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates: [-77,37.9]
    },
    properties: {
      'marker-symbol': 'star'
    }
  })
}).addTo(map);

Following the route

We create a function, tick(), that moves the marker by setting its placement on each point in the list of coordinates that form the route’s line. The synchronization of the video’s time over the total distance of the path is an estimate since the video has small variations.

// a shortcut to accessing the line's coordinate list
var coords = ride.features[0].geometry.coordinates,
    i = 0;

function tick() {
  marker.setLatLng([coords[i][1], coords[i][0]]);

  // ensure the marker doesn't fall off the end of
  // the list of coordinates.
  // 18ms is the time interval between points
  if (++i < coords.length) setTimeout(tick, 18);
}

// start the animation
tick();

Binding the popup

Finally, we bind the video to the marker’s popup and set the popup’s latitude and longitude to pan with the marker.

marker.bindPopup('<iframe src="https://player.vimeo.com/video/69426498?title=0&amp;byline=0&amp;portrait=0&amp;autoplay=1" width="200" height="150" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>', {
  keepInView: false,
  autoPan: false,
  closeButton: false,
  maxWidth: 1000
}).openPopup();

marker._popup.setLatLng = function(latlng) {
  this._latlng = L.latLng(latlng);
  this._updatePosition();
  this._adjustPan();
};

The marker._popup.setLatLng is a minor hack to prevent the video from resetting when changing the popup position - a quirk that will be fixed in the next MapBox.js version.

Wrap up

You can continue to extend this example with time sliders, custom popups, and clean styles for routes and markers. Check out a complete example on our expanding examples page and start adding some new perspectives to your routes.