How can create an offline cache of a large number of SLIPPY tile (PNG, 256x256) inside a web browser and then display them from that offline cache. For example, can one use HTML5 IndexedDB as an storage location for offline map tiles?

  • I did the same thing ;> btw, what is your question exactly?
    – U2ros
    May 28, 2013 at 19:53
  • No question. I wanted to share what I did with this community who have been helpful it getting this to work.
    – Dr.YSG
    May 28, 2013 at 20:03
  • We do appreciate the community nature of this post. That said - This is not really appropriate for this site. However asking a question and answering it yourself is. So please compose an approriate question for the answer and then mark it as the answer. We will see after you get a question posed if it remains open and perhaps moves to community wiki as there could possibly be more than one solution to a potential question.
    – Brad Nesom
    May 28, 2013 at 20:51
  • OK, I rephrased the question so that it better matches the answer. I think that is what you are asking for. I fixed this a while back, but for some reason it looks like codepen went backwards. OK, I updated it to a new set of tiles. Need to see why the cross domain with Google Drive is not working now, sigh
    – Dr.YSG
    May 29, 2013 at 16:59

1 Answer 1


Here is one way to do that:

Components used:

  1. Leaflet
  2. PouchDB (a framework that uses indexedDB in your browser)
  3. XHR2 (XMLHTTP) to fetch the files, since JQUERY does not yet support binary blob XMLHTTP
  4. KendoUI (an HTML5 web control library)

Running the Demo:


  1. Delete any old DB (Press the Delete Button)
  2. Reload the page
  3. Wait till Status is READY
  4. Press [Download Tiles]

This should load 341 blobs from Google Drive (NASA Blue World, in EPSG 3857 projection). It will show a sample image when it is done. Sorry, FireFox has a poor implementation of IDB, so it is very slow (FF uses SQLLite a relational database, and IDB is no-SQL).

Once you have done that, then try:


Which will show that there is a manifest, and 341 tiles, and should overlay the Tiles from PouchDB on your map. You can use the layer control on the left side to turn off the PouchDB layer.

The Algorithm it uses is as follows:

  • Test for presence of XHR2, IndexedDB, and Chrome (which does not have binary blobs, but Base64). and show this status info
  • Fetch a JSON manifest of PNG tiles from GoogleDrive (I have 341 PNG tiles, each 256x256 in size). The manifest lists their names and sizes.
  • Store the JSON manifest in the DB
  • MVVM and UI controls are from KendoUI http://www.kendoui.com/ (This time I did not use their superb grid control, since I wanted to explore CSS3 Grid Styling).
  • XHR2 is from: https://github.com/p-m-p/xhr2-lib/blob/master/test/index.html
  • I am using the nightly build of PouchDB
  • All files PNG file are stored on Google Drive (NASA Blue Marble). \
  • I created the tile pyramid with Safe FME 2013 Desktop. http://www.safe.com/fme/fme-technology/fme-desktop/overview

Before Pressing the button "Download Tiles" Check to see that the manifest has been stored in the DB, and that 341 tiles are present. If you already ran the test then your PouchDB is going to already have tiles in the DB, and you will get errors. In that case, Press Delete DB, and then reload the page.

When you press "Download Tiles" The following steps occur:

  • The Manifest is fetched from the DB
  • A XHR2 Fetch loop grabs the PNG blobs from GoogleDrive.
  • As loop runs, it starts saving the Blobs into PouchDB.
  • Note: Fetching and Saving are on overlapped threads (think co-routines), since those (fetch & store) operations are running async on separate threads.
  • When the Fetch loop is done it reports the elapsed time.
  • Note: This time is not pure Fetch work, since PouchDB putAttachments() are running in parallel.
  • When all the Tiles are saved, it will report full statistics, and display a tile fetched from PouchDB.
  • The Blob-Rate the total fetch and store time per each png tile

Leaflet Map Display

The key idea in getting Leaflet to display maps is to use Ishmael Smyrnow's Functional Tile plug-in: https://github.com/ismyrnow/Leaflet.functionaltilelayer. You will need to use JQUERY DEFFER to allow the PouchDB to asynchronously fetch the tiles from the DB. You also need to understand CreateURL() to create a binary blob url which is used in the tag to show the raster image.

I create my database tile layer this way:

function dbMap() {
    var label = {};
    var settings = {
        tms: false,
        opacity: 0.6,
        errorTileUrl: "./images/EmptyTile.png"
    var layer = new L.TileLayer.Functional(function (view) {
        var deferred = new jQuery.Deferred(); // this is what gets returned
        var id = view.zoom + "-" + view.tile.column + "-" + view.tile.row;
        DB.getAttachment(id + "/pic", function (err, response) {
            if (err) {
                console.warn("Could find blob id: ", id, " error: ", err.error, " reason: ", err.reason, " status: ", err.status);
            } else {
                var blob = response;
                var imgURL = URL.createObjectURL(blob);
                deferred.resolve(imgURL); // let leaflet know we're done, and give it the URL
                URL.revokeObjectURL(imgURL); // not sure if we're revoking it too soon here
        return deferred;
    }, settings);
    label["Pouch DB"] = layer;
    $.extend(OverLayers, label);


Right now Chrome is running fine. Firefox is very slow. I found this out a few months when I did a native IndexedDB API. So I don't think this is a PouchDB issue. Probably more due to FireFox using SQLlite which is a relational approach to a no-SQL DB.

IE10 is not working. This is sad, since my prior tests with IE10 shows it has a fantastically fast IndexedDB solution: https://stackoverflow.com/questions/14113278/storing-image-data-for-offline-web-application-client-side-storage-database

  • I wish your demo worked :(
    – Steven Lu
    Aug 10, 2015 at 2:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.