如何使用maplibre-gl-js的addProtocol加载本地矢量瓦片.mbtiles文件
Cordova环境下MapLibre GL JS加载本地mbtiles矢量瓦片解决方案
前置依赖准备
首先安装支持二进制读取的Cordova SQLite插件:cordova plugin add cordova-sqlite-ext
确保你的.mbtiles文件放在Cordova应用可访问的路径,比如打包时预置到www/map/data/目录,和样式中配置的路径对应即可。
核心实现逻辑
addProtocol回调的核心逻辑分为4步:解析请求参数、转换瓦片坐标系、查询mbtiles数据库、返回瓦片数据给MapLibre,完整代码示例如下:
// 提前缓存已打开的mbtiles数据库实例,避免重复打开损耗性能 const mbtilesDbCache = new Map(); maplibregl.addProtocol('mbtiles', (params, callback) => { // 1. 解析请求参数 const url = new URL(params.url); const mbtilesPath = url.host + url.pathname; // 提取得到 map/data/test.mbtiles const { z, x, y } = params; // MapLibre自动传入当前请求的瓦片层级和坐标 // 2. 转换Y轴坐标:mbtiles默认使用TMS坐标系,Y轴和Web墨卡托XYZ坐标系相反 const tmsY = (1 << z) - 1 - y; // 3. 打开/复用mbtiles数据库 let db = mbtilesDbCache.get(mbtilesPath); if (!db) { db = window.sqlitePlugin.openDatabase({ name: mbtilesPath.split('/').pop(), location: 'default', createFromLocation: 1 // 从www目录加载预置的mbtiles文件 }); mbtilesDbCache.set(mbtilesPath, db); } // 4. 查询瓦片数据 db.executeSql( 'SELECT tile_data FROM tiles WHERE zoom_level = ? AND tile_column = ? AND tile_row = ?', [z, x, tmsY], (res) => { if (res.rows.length === 0) { // 无对应瓦片,返回空 callback(null, null, {}); return; } // 把二进制pbf格式瓦片转成Uint8Array const tileBuffer = new Uint8Array(res.rows.item(0).tile_data); // 回调返回数据,指定正确的矢量瓦片content-type callback(null, tileBuffer, { 'Content-Type': 'application/vnd.mapbox-vector-tile' }); }, (err) => { // 查询出错回调 callback(err); } ); });
常见问题排查
- 瓦片请求成功但地图无内容:确认样式中配置的图层名称和mbtiles内置的矢量图层名称完全一致,可先用桌面工具打开mbtiles查看图层信息
- 数据库打开失败:检查mbtiles文件路径是否正确,若文件放在应用沙箱而非预置www目录,需修改
openDatabase的路径配置 - 瓦片错位:确认TMS Y轴转换逻辑是否正确,部分特殊打包的mbtiles可能不需要翻转,可注释转换逻辑测试
内容的提问来源于stack exchange,提问作者Hollul
相关产品推荐
相关产品推荐

