Pacific Side

20 February 2015

Mapbox GL JS with Offline Vector Tiles on Cordova

Update:

Check out these repositories that do what is discussed in Solution 2 here:
https://github.com/trevorpowell/mapbox-gl-js-cordova-offline
https://github.com/trevorpowell/mapbox-gl-js-cordova-offline-example

Original Post:

Seen some questions about using Mapbox GL with offline vector tiles online as I've been looking into it for my own projects, and thought I might post some of what I've found. This is mainly for use cases where you might want an app for hiking, international use without data roaming, etc. There is a ticket open for offline support in the native version of Mapbox GL, but I wanted to see how it might work to use the JS version in a hybrid mobile app (Apache Cordova, AppGyver Steroids, etc.) since WebGL is supported in iOS and Android webviews now. I saw some discussion of this about two years ago with raster tiles generated in Mapbox Tilemill. My experience back then was that performance was slower when using a SQLite plugin in Cordova to load the tiles from the MBTiles database on demand, but it was better when I extracted the PNG files from the MBTiles database. Obviously, then you lose the benefits of MBTiles — deduplication of identical tiles and not having a ton of files to store. My hope was that with vector tiles being lighter weight, performance in a hybrid app might be better.

Mapbox Studio is to vector tiles what Tilemill was to raster tiles. Mapbox GL is another generation beyond Mapbox Studio — the vector tile sources are the same but the styling is different. A new style editor for Mapbox GL seems to be in the works, but for now there is a guide to follow. Mapbox Studio allows you to export vector tiles as an MBTiles database. Once exported, you can either serve the tiles from the MBTiles file or extract the tiles and serve them as PBF files. There is an example here on serving from an MBTiles file with Node.js that uses Mapbox's Tilelive. It was helpful in understanding some of how Mapbox GL and vector tiles work. Without a Node.js server in a hybrid mobile app, you would have to do things differently. Here are two possibilities on Cordova and some options for each.

Solution 1 – Extract vector tile PBF files from MBTiles database

To start with, use MBUtil to extract the vector tiles as PBF files. For example:

./mb-util --image_format=pbf test.mbtiles test

The files will be gzipped so without a way to add a gzip header when serving them, you could gunzip them:

gzip -d -r -S .pbf *

And re-add the PBF file extension:

find . -type f -exec mv '{}' '{}'.pbf \;

Appgyver Steroids runs a web server on the device that Mapbox GL JS can use when making XHR requests for the style JSON file (or you could just pass a JSON object to Mapbox GL JS for the style instead of a file reference) and the vector tile files. Plain Cordova does not have a web server, but you can use plugins like these to add one:

An alternative to using a web server plugin on Cordova might be to override the methods in Mapbox GL JS that make the calls for the style JSON and vector tiles and instead have them use the Cordova File plugin. Maybe in here:

Solution 2 – Serve vector tiles from MBTiles database using SQLite plugin

This would likely be the better solution; the only question is how it would perform in a hybrid app. The idea on Cordova is to use the SQLite plugin here to retrieve the tiles from the MBTiles database:
https://github.com/brodysoft/Cordova-SQLitePlugin

Again, this would require modifying the methods in Mapbox GL JS that load the vector tiles. You may have to gunzip the tile content then and could use Pako to do so:
https://github.com/nodeca/pako

Demos

I have played around with this some using the "touch" branch from the Mapbox GL JS repository:
https://github.com/mapbox/mapbox-gl-js/tree/touch

Here are some small demos on Cordova with very basic offline vector tiles using the Natural Earth coastline data:

Hi Trevor, nice post btw.
I'm a mapping newbie, but interested in using Mapbox-gl-js (MGJ) on Phonegap.

You suggest above that the MGJ library could use MBtile-derived PBF files, over a local [mobile] http connection (cool). I've briefly read about PBF files, in relation to the Open StreetMap project, however:

How might the PBF files created via MBUtils conversion differ from OSM-derived PBF files?

What I'm trying to understand here is, do we NEED to start with MBTile vector file data, to get the mobile-friendly PBF files or could we simply generate MGJ-compatible PBF files directly from OSM data? if not, why not?

Just for further clarification, are PBF files Vector-based?

Thanks

Apologies, late nights will kill ya'!

I've just realised I read your article quite poorly, and yes, you quite clearly state that you are converting to Vector-based PBF files.

My apologies for 'corrupting' blog post.

Sorry I missed your comment for a few days. I only have experience working with PBF files extracted from an MBTiles database exported from Mapbox Studio. I have not worked with ones directly derived from OpenStreetMap. In my use case, I want to combine OSM data with other datasets, so going through Mapbox Studio makes sense. I think serving tiles from the MBTiles database without extracting the files is by far the preferable solution though. I've been heading that direction and have a fork of Mapbox GL JS that does it here:

https://github.com/trevorpowell/mapbox-gl-js-cordova-offline

Hi, thanks for your great article and github repo.

Just trying to follow the (un)known path and found a nice tool to convert the .osm.pbf file to MapboxVectorTiles .mbtiles: you can find it at https://github.com/systemed/tilemaker

Have a nice day!

If you plan on posting code, please enclose it in the <pre><code> tags to preserve formatting.

Language

Archives

Categories

Trevor Powell © 2015. All rights reserved.