For developers who have experience building web maps with Mapbox.js or Leaflet, switching old projects to use Mapbox GL JS can drastically improve the performance of your existing applications. Mapbox GL JS uses WebGL client-side rendering to display your maps, which results in faster loading, smoother transitions when zooming or panning, and greater flexibility to change map data and styles on the fly. These improvements make switching to Mapbox GL JS well worth the effort, so I recently converted Peter’s Courier demo from Mapbox.js to GL.

A full-screen version is also available.

Here are some key tips to illustrate how you can make the switch with your projects!

Adding map layers and data

In the Courier demo, the pickup points for packages are stored as GeoJSON in the browser and constantly updated with new orders. In Mapbox.js, we added those points to the map using L.mapbox.featureLayer(), and with each update of the pickupPoints GeoJSON object we update the layer’s source using featureLayer().setGeoJSON():

var pickups = L.mapbox.featureLayer(pickupPoints).addTo(map);
// when new pickups are added

In Mapbox GL JS, we first add a source to the map, and then create a new layer:

map.addSource('pickups', {
  type: 'geojson',
  data: pickupPoints

  id: 'pickups',
  source: 'pickups',
  type: 'symbol',
  layout: {
    'icon-image': 'pickup'

When new data are added to the pickupPoints object, we update the new layer’s underlying source using setData() instead of updating the layer directly:


Adding custom markers to Mapbox GL Maps

Because feature layers in Mapbox.js are DOM elements, it is possible to use any image file as a marker on the map. In Mapbox GL JS, however, markers are rendered by the GPU, not the browser, so any images you would like to use as markers have to be loaded into a sprite and referenced in your map’s style JSON.

You can add custom markers to a sprite in Mapbox Studio - this handy guide walks you through the whole process. Alternatively, you can use spritezero, our open-source sprite generator to build your sprite from the command line, or on the fly in your application.

Animations in Mapbox GL JS

We can animate DOM elements using CSS, which is how Peter animated the line of the couriers’ paths to their destinations in the original Courier demo. Since we cannot use DOM manipulation, we’ll use the same setData() method on our GeoJSON source that we used in the above pickupPoints example, but this time we’ll use it in conjunction with Turf and the JavaScript method window.requestAnimationFrame just like this example.

function animateCourier(route, destination) {
  // set animation speed at 60x real time
  var speed = 60;
  var duration = route.duration;
  var path = turf.linestring(route.geometry.coordinates);
  var distance = turf.lineDistance(path);
  // get starting time of the animation
  var start =;

  function animate(timestamp) {
    var current_time = timestamp - start;
    // if the animation has reached its destination, 
    // move the courier to the destination and end the animation loop
    if ((current_time * speed) / (duration * 1000) >= 1) {
    } else {
      // find the current distance the courier has traveled along the path
      var current_distance = current_time * speed) / (duration * 1000) * distance;
      var waypoint = turf.along(path, current_distance, "kilometers");
      // continue the animation loop

To learn more about Mapbox GL JS and how you can implement your projects with it, check out our Mapbox GL JS Fundamentals guide, or take a look at some of the examples.