I am developing an application in Apache Cordova that uses vector layers in mbtiles, created with tippecanoe, and I need it to be fully accessible offline. To achieve this, I am using maplibre-gl-js, using addProtocol("custom"), as indicated here
I am using the "tms" scheme since the data in the mbtiles file is in that scheme. When I take the z, x, and y from the url parameters to query the database with SQLite, the {y} parameter is a little offset.
It's not a XYZ / TMS schema problem. Everything is under TMS schema (data, and maplibre source), but the value in maplibre "{y}" parameter, has a little offset, for example, {y} = 10005 in maplibre, versus tile_row 10050 in mbtiles, or {y} = 20011 in maplibre, vs tile_row 20100 in mbtiles.
Mbtiles tile_row has the correct value.
The code i'm using is:
first, add the new protocol.
maplibregl.addProtocol("custom", (params, callback) => {
getTileBufferFromDatabase(params).then(tileBuffer => {
if (tileBuffer) {
callback(null, tileBuffer, null, null);
} else {
callback(new Error(message));
}
});
return { cancel: () => { } };
});
Add the function to query the database, used in the protocol
async function getTileBufferFromDatabase(params) {
const url = new URL(params['url']);
const pathComponents = url.pathname.split('/');
const z = parseInt(pathComponents[6]);
const x = parseInt(pathComponents[7]);
var y = parseInt(pathComponents[8].split('.')[0]);
return new Promise((resolve, reject) => {
db2.executeSql('SELECT BASE64(tile_data) AS base64_tile_data FROM tiles WHERE zoom_level = ? AND tile_column = ? AND tile_row = ?', [z, x, y], (resultSet) => {
if (resultSet.rows.length > 0) {
const base64Data = resultSet.rows.item(0).base64_tile_data;
const rawData = pako.inflate(base64js.toByteArray(base64Data));
resolve(rawData)
} else {
resolve(null);
}
}, (error) => {
reject(error);
});
});
}
Creating the map.
const map = new maplibregl.Map({
container: 'map',
center: [
-4.93911,
37,777985
],
zoom: 14,
tileSize: 512
});
Adding the source with the new protocol "custom".
map.addSource('mbtiles-source', {
type: 'vector',
tiles: ["custom://data/user/com.project.ndvi/databases/{z}/{x}/{y}.pbf"],
tileSize: 512,
minzoom: 14,
maxzoom: 15
});
var ndvi_layer = map.addLayer({
"id": 'ndvi-layer',
"type": 'fill',
"source": 'mbtiles-source',
"source-layer": 'ndvi',
"layout": {},
"paint": {
'fill-color': 'blue',
'fill-opacity': 0.5
}
});
When I query the databse, the {y} parameter is offset.
Any idea why this is happening? Thank you!