Skip to content

Instantly share code, notes, and snippets.

@unxed
Created October 25, 2011 21:14
Show Gist options
  • Save unxed/1314300 to your computer and use it in GitHub Desktop.
Save unxed/1314300 to your computer and use it in GitHub Desktop.
FileSystem API-based cache for Kothic-JS - v.0.02
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder;
Object.size = function(obj) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
if (typeof(window.requestFileSystem) != 'undefined')
{
// window.requestFileSystem(TEMPORARY, 1024 * 1024 * 128, onInitFs, errorHandler);
window.requestFileSystem(0, 1024 * 1024 * 128, onInitFs, errorHandler);
}
function onInitFs(fs_) {
window.fs = fs_;
}
function errorHandler(e) {
var msg = '';
switch (e.code) {
case FileError.QUOTA_EXCEEDED_ERR:
msg = 'QUOTA_EXCEEDED_ERR';
break;
case FileError.NOT_FOUND_ERR:
msg = 'NOT_FOUND_ERR';
break;
case FileError.SECURITY_ERR:
msg = 'SECURITY_ERR';
break;
case FileError.INVALID_MODIFICATION_ERR:
msg = 'INVALID_MODIFICATION_ERR';
break;
case FileError.INVALID_STATE_ERR:
msg = 'INVALID_STATE_ERR';
break;
default:
msg = 'Unknown Error';
break;
};
console.log('Error: ' + msg);
}
L.TileLayer.Kothic = L.TileLayer.Canvas.extend({
options: {
tileSize: 256 * 4,
zoomOffset: 2,
minZoom: 2,
maxZoom: 22,
updateWhenIdle: true,
unloadInvisibleTiles: true,
attribution: 'Map data &copy; 2011 OpenStreetMap contributors, Rendering by <a href="http://github.com/kothic/kothic-js">Kothic JS</a>',
async: true,
buffered: true
},
initialize: function(options) {
L.Util.setOptions(this, options);
this._canvases = {};
this._debugMessages = [];
var layer = this;
window.onKothicDataResponse = L.Util.bind(this._onKothicDataResponse, this);
},
saveToCache: function(canvas, zoom, x, y)
{
if ((typeof(fs) != 'undefined') && (typeof(window.requestFileSystem) != 'undefined'))
{
// we now have correct filesystem object to use for cache
fs.root.getFile(x + '_' + y + '_' + zoom + '.txt', {create: true}, function(fileEntry) {
console.log('saving to cache: '+fileEntry.fullPath);
// Create a FileWriter object for our FileEntry.
fileEntry.createWriter(function(fileWriter) {
fileWriter.seek(0); // Start write position at EOF.
var bb = new BlobBuilder(); // Note: window.WebKitBlobBuilder in Chrome 12.
bb.append(canvas.toDataURL("image/png"));
fileWriter.write(bb.getBlob('text/plain'));
bb = null;
console.log('saved to cache: '+fileEntry.fullPath);
}, errorHandler);
}, errorHandler);
}
},
_onKothicDataResponse: function(data, zoom, x, y) {
var key = [zoom, x, y].join('/'),
canvas = this._canvases[key],
buffered = this.options.buffered,
zoomOffset = this.options.zoomOffset,
layer = this;
function onRenderComplete(debugInfo) {
layer.saveToCache(canvas, zoom, x, y);
// TODO move this logic outside
// var debugStr = layer.getDebugStr(debugInfo, x, y, zoom);
// layer._debugMessages.push(debugStr);
// temporary disable debug messages
layer.tileDrawn(canvas);
}
Kothic.render(canvas, data, zoom + zoomOffset, layer._additionalStyle, onRenderComplete, buffered);
delete this._canvases[key];
},
getDebugStr: function(debugInfo, x, y, zoom) {
return '<b>tile ' + x + ':' + y + ':' + zoom + '</b><br />' +
'<table><tr><td>' + debugInfo.layersStyled + ' ms</td><td>layers styled</td></tr>' +
'<tr><td>' + debugInfo.mapRendered + ' ms</td><td>map rendered</td></tr>' +
'<tr><td>' + debugInfo.iconsAndTextRendered + ' ms</td><td>icons/text rendered</td></tr>' +
'<tr><td>' + debugInfo.total + ' ms</td><td>total</td></tr></table>';
},
getDebugMessages: function() {
return this._debugMessages;
},
drawTile: function(canvas, tilePoint, zoom) {
console.log('!!! '+Object.size(this._canvases));
var zoomOffset = this.options.zoomOffset,
key = [(zoom - zoomOffset), tilePoint.x, tilePoint.y].join('/'),
path = '/' + [tilePoint.x, tilePoint.y, (zoom - zoomOffset)].join('_') + '.txt';
console.log('seeking cache for: '+path);
var url = 'http://2g0.ru/map/kothic/tileprxy.php?z=' + (zoom - zoomOffset) + '&x=' + tilePoint.x + '&y=' + tilePoint.y;
var layer = this;
if ((typeof(fs) != 'undefined') && (typeof(window.requestFileSystem) != 'undefined'))
{
fs.root.getFile(path, {}, function(fileEntry) {
fileEntry.file(function(file) {
var reader = new FileReader();
reader.onloadend = function(e) {
var cached_img = new Image();
cached_img.src = this.result;
cached_img.onload = function () {
canvas.getContext('2d').drawImage(cached_img, 0, 0);
layer.tileDrawn(canvas);
console.log('shown from cache: '+path);
}
};
reader.readAsText(file);
}, function(e) {
layer._canvases[key] = canvas;
layer._loadScript(url);
errorHandler(e);
console.log('requesting from server: '+path);
} );
}, function(e) {
layer._canvases[key] = canvas;
layer._loadScript(url);
errorHandler(e);
console.log('requesting from server: '+path);
} );
} else {
layer._canvases[key] = canvas;
layer._loadScript(url);
}
},
setAdditionalStyle: function(fn) {
this._additionalStyle = fn;
// TODO implement layer.redraw() in Leaflet
if (this._map && this._map._container) {
this._reset();
this._update();
}
},
_loadScript: function(url) {
var script = document.createElement('script');
script.src = url;
script.charset = 'utf-8';
document.getElementsByTagName('head')[0].appendChild(script);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment