indexeddb离线地图瓦片缓存需以z/x/y字符串为主键建tiles对象库,用arraybuffer批量写入(50–200条/事务),拦截地图请求优先查idb并返blob url,辅以version字段和zoomindex索引实现定向清理与版本管理。

用 IndexedDB 做离线地图瓦片缓存,核心不是“能不能存”,而是“怎么存得快、查得准、不爆 quota、还能和地图库无缝配合”。它不是简单把图片塞进去,而是一套围绕 z/x/y 结构、ArrayBuffer 读写、请求拦截与按需加载的协同方案。
数据库结构:用 z/x/y 字符串当主键,别嵌套
瓦片天然有唯一路径,比如 12/2048/1365(缩放级别12,横坐标2048,纵坐标1365),直接拼成字符串作主键最简洁高效:
- 建一个名为 tiles 的 objectStore,
keyPath: "id" - 每条记录形如:
{ id: "12/2048/1365", data: ArrayBuffer, mimeType: "image/png", timestamp: 1719234567000 } - 避免用 {z:12,x:2048,y:1365} 这种对象当 key —— 查询时还得索引复合字段,徒增复杂度
- 如需按缩放级别批量清理(比如删掉所有 z≤8 的旧瓦片),可额外建一个 zoomIndex 索引,
keyPath: "z",但非必需
存瓦片:用 ArrayBuffer + 批量事务,别单条 add
一次下载常含上万瓦片,逐条写入会卡死页面、触发配额警告。必须控制节奏:
- 每次事务写入 50–200 条 记录,用
transaction.objectStore("tiles").add()批量提交 - 用
Promise.all()或递归分片处理,确保顺序完成且不压垮主线程 - 写入前查配额:
navigator.storage.estimate()获取 usage/limit,当 usage > limit × 0.8 时,主动清理过期或低优先级瓦片(如 7 天未访问的) - 别存 Blob —— ArrayBuffer 更轻量、可直接用于 canvas 绘图或 URL.createObjectURL(),配合 mimeType 字段就能还原图像
读瓦片:拦截地图请求,命中就返,不命中再走网络
地图库(如 Leaflet、MapLibre、Cesium)默认发 HTTP 请求,你要把它“劫持”过来优先查 IDB:
- Leaflet:扩展
L.TileLayer,重写createTile(),先查 IDB;查到则tile.src = URL.createObjectURL(new Blob([arrayBuffer], {type: mimeType})) - MapLibre GL:用
customSource实现loadTile回调,返回{ data: Uint8Array, cacheControl: 'no-store' } - Cesium:通过
requestImage钩子或自定义TileProvider拦截影像请求 - 务必设置
crossOrigin: "anonymous"和正确 MIME 类型,否则 Canvas 渲染时可能因跨域污染失败
清理与版本管理:支持定向清除,防脏数据堆积
用户可能多次下载不同区域、不同版本的地图包,不能让旧数据越积越多:
- 给每批瓦片加 version 标签(如 "beijing-2026-q2"),存进 record 的 version 字段
- 清理时按 version 删除,例如
store.index("version").openKeyCursor(IDBKeyRange.only("shanghai-2025")) - 结合 timestamp 字段做 LRU 清理:定期删除 30 天未访问且非当前活跃版本的瓦片
- 提供 UI 入口让用户手动选择清除某区域或某缩放范围,增强可控性
不复杂但容易忽略。关键在结构设计克制、写入节奏可控、读取路径贴近地图库原生逻辑,而不是堆功能。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











