Map libraries comparison: Leaflet vs Mapbox GL vs OpenLayers – trends and statistics

When you need to add a map to your application, the first question that pop-ups in your head is “Which map library to use?”. If you start to google, you’ll find out soon that at the moment the Leaflet, Mapbox GL, OpenLayers are the most popular libraries for displaying interactive maps on a web page.

In this article, we want to compare the libraries and check actual trends and statistics. So you can choose the most promising option for you.

We used NPM Trends and Google Trends to get the data and create beautiful visualizations.

Leaflet vs Mapbox GL vs OpenLayers

LeafletMapbox GLOpenLayers
The open-source JS library for interactive maps. A simple interface, great documentation, and a huge community allow you to get results and solve your tasks quickly.
Unfortunately, not developed actively any longer.
Powerful and effective SDK for web maps developed by Mapbox. As Leaflet library creators developed Mapbox GL now, you can see some similarities between 2 libraries. However, Mapbox GL gives you more opportunities, data visualization options and opens the vector maps world for you.Familiar with GIS technologies? Then OpenLayers can be the perfect option for you! The OpenLayers is not only about displaying maps, but also visualizing and analyzing geographical data. It could be a bit more complicated at the beginning but allows you to create more powerful solutions.
Vector maps support
The core functionality of Leaflet doesn’t have vector tiles support. Nevertheless, you can visualize vector tiles by using external plugins. For example, Mapbox GL Leaflet.
Vector maps support
Mapbox is a pioneer in vector maps technologies. The Mapbox Style Specification for vector maps, which is very popular now and used by Geoapify as well, is natively supported by Mapbox GL.
Vector maps support
OpenLayers has native support for vector maps but the ol-mapbox-style plugin is required to create a map with Mapbox Style Specification.
JSFiddle code sampleJSFiddle code sampleJSFiddle code sample

NPM trends for the map libraries

The number of downloads for npm packages gives a great indication of how popular each library is. Here is npm trends statistics for the last 12 month:

npm trends: Leaflet, Mapbox GL, Openlayers

And the charts look really interesting! Except for temporary Mapbox GL usage spike in February – June 2020, Leaflet keeps on par with Mapbox GL. In comparison with other map libraries, OpenLayers looks stable. And all three top mapping libraries demonstrate steady growth – there is no indication of developers switching from one to another.

In the same time, Open Layers usage seems to be growing faster than Leaflet or Mapbox GL. If we check the statistics for OpenLayers only, we can prove that:

npm trends: OpenLayers

Statistics from GitHub show us how many times a library was “stared”:

GitHub statistics: Leaflet, Mapbox GL, Openlayers

And here we see that Leaflet is 4.5 times more popular at the moment than Mapbox GL, and 4 times more popular than OpenLayers.

Google Trends for the map libraries

Google search keywords trends are another good measure of popularity. However, here we’ve faced with a problem. While “Leaflet” and “OpenLayers” are unique names, “Mapbox GL” is often googled as “Mapbox”. So we decided to add both “Mapbox GL” and “Mapbox” to give you an overview:

The chart shows that interest in each library more or less stays on the same level. In other hands, statistics by regions provide some interesting results as well:

Map libraries comparison by region

Leaflet leads the keywords list in almost all countries. However, Mapbox/Mapbox GL is popular in China, the United States, Belorus, and Canada. And OpenLayers is in request in South Korea, Croatia, and Finland.

Conclusions

It’s always a matter of taste when you are trying to choose the best from several good options. Nevertheless, we hope that the numbers and charts we gave you in this article will help you to make the right decision.

Leaflet, Mapbox GL, and OpenLayers code samples

We’ve created code samples to help you develop a custom map for your website. Visit the Geoapify Documentation page to learn how to add a map to your React-, Angular-, or Vue-webapp.

Geoapify offers map tiles that can be used with all the libraries. We provide vector and raster maps of different styles and colors. Learn more about Geoapify Map Tiles.

Visualizing time series data on the map

In this article, I’ll show how to create a map-based visualization of multi-dimensional data – time, location and value. As an example, I’m going to use the public daily statistics for nCoV-2019 “coronavirus” outbreak.

By the end of January 2020, the “coronavirus” outbreak started to become one of the top world concerns. Despite the high amount of information that authorities and news agencies provide every day, it is surprisingly hard to see the big picture behind all those numbers.

As most situational data, virus outbreak numbers have a clear location component. Therefore map-based visualization can be extremely helpful.

We’re going to take the raw data and create a simple web-based dashboard that looks like this:

Coronavirus outbreak visualization
Coronavirus outbreak visualization

Preparing data

As the first step, I took the daily statistics data kindly made available here by the Center for Systems Science and Engineering at John Hopkins University.

Raw data were normalized, aggregated by date and geocoded with Geoapify Geocoding API. For convenience, the resulting data for each day were represented in the GeoJSON format, that looks like this:

{
        "type": "FeatureCollection",
        "features": [{
          "type": "Feature",
          "geometry": {
            "type": "Point",
            "coordinates": [121.4554, 31.20327]
          },
          "properties": {
            "Place": "Shanghai",
            "Confirmed": 9
          }
        },
        ...
}

Configuring map

As the next step, I created a simple webpage with Mapbox GL data visualization library, “dark” basemap and two layers – “case-circles” and “case-labels”. Both layers configured to use the GeoJSON data source and dynamically take the number of confirmed cases from each GeoJSON Feature “properties.Confirmed” field.

// please get your own free ApiKey at https://myprojects.geoapify.com
var geoapifyApiKey = '7e99a2fb2e9b41ae9e40742f24c33d75';

var map = new mapboxgl.Map({
  container: 'map',
  style: `https://maps.geoapify.com/v1/styles/dark-matter/style.json?apiKey=${geoapifyApiKey}`,
  center: [15, 21],
  refreshExpiredTiles: false,
  zoom: 1.1
});

map.on('load', function() {
  map.addSource('cases', {
    'type': 'geojson',
    data: null
  });

  map.addLayer({
    'id': 'case-circles',
    'type': 'circle',
    'source': 'cases',
    'paint': {
      'circle-color': '#FF0000',
      'circle-opacity': 0.5,
      'circle-radius': [
        'interpolate',
        ["exponential", 0.9],
        ['get', 'Confirmed'],
        1,
        5,
        5000,
        15
      ]
    }
  });

  map.addLayer({
    'id': 'case-labels',
    'type': 'symbol',
    'source': 'cases',
    'layout': {
      'text-field': [
        'to-string', ['get', 'Confirmed']
      ],
      'text-font': [
        'Open Sans Bold',
        'Arial Unicode MS Bold'
      ],
      'text-size': 12
    },
    'paint': {
      'text-color': 'rgba(0,0,0,0.5)'
    }
  });
});

Due to the significant difference in the number of confirmed cases per location, the “case-circles” layer was configured to use an exponential scale, to emphasize new locations as they appear on the map.

Adding interactivity

Additionally, I’ve added the date slide that triggers map update accordingly to the selected date and allows to see outbreak dynamics.

<div class="map-overlay top">
    <div class="map-overlay-inner">
        <h2 id="date"></h2>
        <input id="slider" type="range" min="0" max="1" step="1" value="0" />
        <h2 id="count">Confirmed cases</h2>
    </div>
</div>

<script>
var casesHistory = getCasesHistory()
var dates = Object.keys(casesHistory)

document.getElementById('slider').max = dates.length - 1

function updateMap(dateId) {
  var date = dates[dateId]
  var casesForDate = casesHistory[date]
  document.getElementById('date').textContent = `Date: ${date}`;
  document.getElementById('count').textContent = `Confirmed cases: ${casesForDate.total}`;
  map.getSource('cases').setData(casesForDate.geojson);
}

document
  .getElementById('slider')
  .addEventListener('input', function(e) {
    var dateId = parseInt(e.target.value, 10);
    updateMap(dateId);
});

updateMap(0);
</script>

Going further

I hope that you now have the general idea of how to create similar visualizations. To make it easier, I’ve prepared a free JSFiddle example to help you get started.

Still too complicated? Don’t worry, and get in touch with us. We’ll be happy to help you with your project.

Map animation with Mapbox GL

What can be more eye-catching than smooth, interactive, three-dimensional map animation? Impress your visitors by displaying your map data in stunning 3D!

Previously we have compared OpenLayers and Leaflet map libraries. Both are great choices if you want to add interactive map to your website. They are free, battle-tested, extensible and supported by active communities.

But what if you need a very fast, animated, eye-catching 3D map? Both Leaflet API and OpenMapLayersAPI do not support 3D and free-form map rotation. In this case Mapbox GL map library can be a great option.

Mapbox GL JS is one of the most advanced JavaScript map rendering libraries when it comes to smooth interactive animation. Mapbox GL API is slightly harder to use and not compatible with existing Leaflet plugins and examples. But it is using hardware-accelerated WebGL technology to dynamically draw data with the speed and smoothness of a video game.

In this article I’ll show you how to animate and implement 3D map rotation around a selected point. The end result should look like this:

Map rotation animation in 3D with Mapbox GL

If you short on time and just looking for the complete HTML code, you can find it at the bottom of the page.

Setting up our 3D map

As first step, we need to add imports for Mapbox GL library and its CSS style sheet into the HEAD of our page

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mapbox-gl/0.53.1/mapbox-gl.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/mapbox-gl/0.53.1/mapbox-gl.js"></script>

Once imported, we can define a <div> element which will host map visualization and add Javascript code which will initialize Mapbox GL to render our map in 3D with specified initial location, zoom, pitch and bearing. Please do not forget to put your real API key instead of “YOUR_API_KEY” placeholder in the map tiles URL.

<div id='map'></div>
<script>
var map = new mapboxgl.Map({
    container: 'map',
    style: {
        "version": 8,
        "sources": {
            "basemap": {
                "type": "raster",
                // map tile source 
                "tiles": [
                    "https://maps.geoapify.com/v1/tile/carto/{z}/{x}/{y}.png?api_key=YOUR_API_KEY"
                ],
                "tileSize": 256
            }
        },
        "layers": [{
            "id": "basemap",
            "type": "raster",
            "source": "basemap",
            "minzoom": 0,
            "maxzoom": 22
        }]
    },
    center: [-73.991462, 40.724637], // starting position
    zoom: 12, // starting zoom
    pitch: 60, // starting pitch in degrees
    bearing: 0, // starting bearing in degree
});

This should give us basic interactive 3D map. You should be able to move the map to a different locations, zoom in and out, and change view angle.

Interactive 3D map view of Manhattan, NY
Interactive 3D map view of Manhattan, NY

Adding map rotation animation

As next step, let’s add dynamic map animation, which will change view angle to create effect of flying around the map center. Please add the following code into our <script> block and refresh the page:

function rotateCamera(timestamp) {
    // rotate at approximately ~10 degrees per second
    map.rotateTo((timestamp / 100) % 360, {duration: 0});
    // request the next frame of the animation
    requestAnimationFrame(rotateCamera);
}

map.on('load', function () {
    // start the animation
    rotateCamera(0);
});

Final steps

As the last step, let’s add basic map navigation controls and basemap attribution.

// map navigation controls
map.addControl(new mapboxgl.NavigationControl());

// attribution
map.addControl(new mapboxgl.AttributionControl({
	compact: false,
	customAttribution: 'Powered by <a href="https://geoapify.com/">Geoapify</a> | © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}));
Complete map with controls and attribution
Complete map with controls and attribution

Complete HTML code

Final version of the HTML page could look like this. Please feel free to copy the code, insert API key and open it in your browser to see how it works.

<html>
<head>
    <meta charset='utf-8' />
    <title>Mapbox GL example: rotate map animation in 3D</title>
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mapbox-gl/0.53.1/mapbox-gl.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/mapbox-gl/0.53.1/mapbox-gl.js"></script>
    <style>
        body { margin:0; padding:0; }
        #map { position:absolute; top:0; bottom:0; width:100%; }
    </style>
</head>
<body>

<div id='map'></div>
<script>
var map = new mapboxgl.Map({
    container: 'map',
    style: {
        "version": 8,
        "sources": {
            "basemap": {
                "type": "raster",
                // map tile source 
                "tiles": [
                    "https://maps.geoapify.com/v1/tile/carto/{z}/{x}/{y}.png?api_key=YOUR_API_KEY"
                ],
                "tileSize": 256
            }
        },
        "layers": [{
            "id": "basemap",
            "type": "raster",
            "source": "basemap",
            "minzoom": 0,
            "maxzoom": 22
        }]
    },
    center: [-73.991462, 40.724637], // starting position
    zoom: 12, // starting zoom
    pitch: 60, // starting pitch in degrees
    bearing: 0, // starting bearing in degree
});

function rotateCamera(timestamp) {
    // rotate at approximately ~10 degrees per second
    map.rotateTo((timestamp / 100) % 360, {duration: 0});
    // request the next frame of the animation
    requestAnimationFrame(rotateCamera);
}

map.on('load', function () {
    // start the animation
    rotateCamera(0);
});

// map navigation controls
map.addControl(new mapboxgl.NavigationControl());

// attribution
map.addControl(new mapboxgl.AttributionControl({
	compact: false,
	customAttribution: 'Powered by <a href="https://geoapify.com/">Geoapify</a> | © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}));
	
</script>

</body>
</html>

Summary

Mapbox GL generally requires more JavaScript code to be written than Leaflet and can be more complicated to maintain.

So, you may ask when to use Leaflet and when to use Mapbox GL?

The answer is simple – if you don’t need 3D and extremely fast animation then Leaflet would be the best choice. It has biggest community, best documentation, extensive set of plugins and works well in any situation. And if you really need advanced 3D maps with animations and top rendering speed on modern devices – then Mapbox GL is your friend.