-
-
Save coomsie/1446773 to your computer and use it in GitHub Desktop.
Leaflet Offline Tiles using SQL Storage
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* L.TileLayer.LocalCache : A tile layer using SQL Storage, if available. | |
*/ | |
L.TileLayer.LocalCache = L.TileLayer.extend({ | |
options: { | |
minZoom: 0, | |
maxZoom: 18, | |
tileSize: 256, | |
subdomains: 'abc', | |
errorTileUrl: '', | |
attribution: '', | |
opacity: 1, | |
scheme: 'xyz', | |
noWrap: false, | |
unloadInvisibleTiles: L.Browser.mobileWebkit, | |
updateWhenIdle: L.Browser.mobileWebkit, | |
TOPO250_ZOOM_MIN : 5, | |
TOPO250_ZOOM_MAX : 12, | |
TOPO50_ZOOM_MIN :13, | |
TOPO50_ZOOM_MAX : 15, | |
PROVIDER: "Topo", | |
mimetype:'image/png' | |
}, | |
initialize: function(url, tilestorage, options) { | |
this._url = url; | |
this.tilestorage = storage; | |
if (typeof this.options.subdomains == 'string') { | |
this.options.subdomains = this.options.subdomains.split(''); | |
} | |
L.Util.setOptions(this, options); | |
}, | |
_loadTile: function(tile, tilePoint, zoom) { | |
tile._layer = this; | |
tile.onload = this._tileOnLoad; | |
tile.onerror = this._tileOnError; | |
this.getTileUrl(tile, tilePoint, zoom); | |
}, | |
getTileUrl: function(tile, tilePoint, zoom) { | |
var fallback; | |
var subdomains = this.options.subdomains, | |
s = this.options.subdomains[(tilePoint.x + tilePoint.y) % subdomains.length]; | |
if(zoom >= this.options.TOPO250_ZOOM_MIN && zoom <= this.options.TOPO250_ZOOM_MAX) { | |
this._url= "http://{s}.domainname/{z}-{x}-{y}.png"; | |
fallback = this._url | |
.replace('{s}', s) | |
.replace('{z}', zoom) | |
.replace('{x}', tilePoint.x) | |
.replace('{y}', tilePoint.y); | |
} | |
else if(zoom >= this.options.TOPO50_ZOOM_MIN && zoom <= this.options.TOPO50_ZOOM_MAX) { | |
this._url= "http://{s}.domainanme/{z}-{x}-{y}.png"; | |
fallback = this._url | |
.replace('{s}', s) | |
.replace('{z}', zoom) | |
.replace('{x}', tilePoint.x) | |
.replace('{y}', tilePoint.y); | |
} else { | |
fallback = blankTile; | |
} | |
//Ti.API.log(fallback); | |
// fallback = this._url | |
// .replace('{s}', s) | |
// .replace('{z}', zoom) | |
// .replace('{x}', tilePoint.x) | |
// .replace('{y}', tilePoint.y); | |
this.tilestorage.loadTile(this.options.mimetype, this.options.PROVIDER,tile, zoom, tilePoint.x, tilePoint.y, fallback); | |
} | |
}); | |
/* | |
* $.TileStorage : A tile SQL storage. (using Jquery, TODO: rewrite for Leaflet class model!) | |
*/ | |
(function($){ | |
$.TileStorage = function(options) { | |
var self = this; | |
var settings = $.extend({ | |
dbname: 'TilesDB', | |
version: '1.0', | |
comment: 'Leaflet Tile Database', | |
size: 20000 | |
}, options || {}); | |
self.db = null; | |
self.initTiles = function (reset) { | |
self.db = openDatabase(settings.dbname, settings.version, settings.comment, settings.size); | |
if(!self.db) { | |
alert('Database open failed.'); | |
} | |
if (reset) { | |
console.log("Creating tables..."); | |
self.db.transaction(function(tx) { | |
tx.executeSql("DROP TABLE tiles;", [], function(tx, result) {}, function(tx, error) {}); | |
tx.executeSql("CREATE TABLE tiles (z INT, x INT, y INT, data TEXT);", [], | |
function(tx, result) { | |
console.log('Database created.'); | |
}, | |
function(tx, error) { | |
self.__dbError(error); | |
} | |
); | |
}); | |
} | |
}; | |
self.storeTiles = function (data) { | |
if (!self.db) { | |
self.initTiles(true); | |
} | |
var nbtiles = 0; | |
$(data.tiles).each(function (index, value) { | |
var z = value.tile[0], | |
x = value.tile[1], | |
y = value.tile[2], | |
tiledata = "data:" + data.mimetype + ";base64," + value.data; | |
self._storeTile(z, x, y, tiledata, function(tx, result) { | |
nbtiles++; | |
}); | |
}); | |
console.log("Stored " + nbtiles + "/" + data.tiles.length + " tiles."); | |
}; | |
self._storeTile = function (z, x, y, data, success) { | |
self.db.transaction(function (tx) { | |
tx.executeSql("INSERT INTO tiles (z, x, y, data) VALUES (?, ?, ?, ?);", [z, x, y, data], | |
success, | |
function(tx, error) { | |
self.__dbError(error); | |
} | |
); | |
}); | |
}; | |
self.loadTile = function (mimetype,provider, tile, z, x, y, fallback) { | |
if (!self.db) { | |
self.initTiles(); | |
} | |
self.db.transaction(function (tx) { | |
tx.executeSql("INSERT INTO tiles (z, x, y, data) VALUES (?, ?, ?, ?);", [z, x, y, data], | |
success, | |
function(tx, error) { | |
self.__dbError(error); | |
} | |
); | |
}); | |
//Create tile Object for saving tiles | |
var tileObject = new Object; | |
tileObject.image = new Image(); //tile; | |
tileObject.provider = provider; | |
tileObject.x = x; | |
tileObject.y = y; | |
tileObject.z = z; | |
tileObject.xyz = x +","+y+","+z; | |
tileObject.src = fallback; | |
tileObject.mimetype=mimetype; | |
var xyz = new String(""); | |
xyz = x +","+y+","+z; | |
self.db.transaction(function (tx) { | |
//tx.executeSql("SELECT data FROM tiles WHERE z = ? AND x = ? AND y = ?", [z, x, y], | |
//Ti.API.log(xyz); | |
tx.executeSql("SELECT data FROM tiles WHERE provider = ? AND xyz = ?",[tileObject.provider , tileObject.xyz], | |
function(tx, result) { | |
if (result.rows.length > 0) { | |
tile.style.border = 'dotted 3px blue'; | |
tile.src = result.rows.item(0).data; | |
} | |
else { | |
tile.style.border = 'dotted 3px red'; | |
self.populateCache(tileObject); | |
tile.src = fallback; | |
} | |
}, | |
function(tx, error) { | |
self.__dbError(error); | |
} | |
); | |
}); | |
}; | |
self.__dbError = function (err) { | |
Ti.API.log(err); | |
}; | |
/* | |
* Functions for storing tiles while online to SQL Storage, if available. | |
*/ | |
// from http://stackoverflow.com/questions/934012/get-image-data-in-javascript | |
self.getBase64Image = function (img,mimetype) { | |
canvas = document.createElement("canvas"); | |
canvas.width = img.width; | |
canvas.height = img.height; | |
ctx = canvas.getContext("2d"); | |
ctx.drawImage(img, 0, 0); | |
return canvas.toDataURL(mimetype,'quality=20'); | |
}; | |
self.populateCache = function(tileObject){ | |
// using canvas toDataURL method to generate base64 string | |
tileObject.image.src=tileObject.src; | |
tileObject.image.onload = function(){ | |
tileObject.data = self.getBase64Image(tileObject.image, tileObject.mimetype); | |
self.writeTileToCache(tileObject); | |
} | |
}; | |
self.writeTileToCache = function(tileObject){ | |
var d=new Date(); | |
d.toLocaleDateString(); | |
var timestamp = d; | |
var provider = tileObject.provider; | |
var xyz=tileObject.xyz; | |
var x = tileObject.x; | |
var y = tileObject.y; | |
var z = tileObject.z; | |
var data = tileObject.data; | |
self.db.transaction(function (tx) { | |
tx.executeSql("INSERT INTO tiles (provider,xyz, x, y, z, timestamp,data) VALUES (?,?,?,?,?,?,?);", [provider,xyz,x,y,z,timestamp,data], | |
function(tx, result) { | |
}, | |
function(tx, error) { | |
self.__dbError(error); | |
} | |
); | |
}); | |
tileObject = null; //release tileObject | |
}; | |
}; | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
added some save back to db options when browsing via the internet
also can cope with my different urls at different zoom levels