maplibre-tilepackage-protocol 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -48
- package/dist/bundle.js +5657 -0
- package/dist/bundle.js.map +1 -0
- package/dist/index.esm.js +2060 -0
- package/dist/index.esm.js.map +1 -0
- package/eslint.config.mjs +28 -0
- package/package.json +42 -22
- package/rollup.config.mjs +45 -0
- package/src/default-decompress.js +11 -4
- package/src/get-header-and-filelist.js +42 -3
- package/src/index.js +175 -103
- package/src/maplibre-gl-js-protocol.js +28 -12
- package/src/shared-promise-cache.js +23 -0
- package/src/source.js +19 -4
- package/src/tilecutter/IMPLEMENTATION_PLAN.md +135 -0
- package/src/tilecutter/subdivide.js +247 -0
package/README.md
CHANGED
|
@@ -1,78 +1,146 @@
|
|
|
1
1
|
# maplibre-tilepackage-protocol
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Custom MapLibre GL JS protocol for reading Esri `TPKX` (raster) and `VTPK` (vector) TilePackage archives.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Works with:
|
|
6
|
+
|
|
7
|
+
- Local files selected via an `<input type="file">` (no server required)
|
|
8
|
+
- Relative or absolute HTTP(S) URLs to remote TilePackages
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
The protocol streams tiles, glyphs and sprites directly from the archive. For VTPK it synthesizes a ready-to-use MapLibre style (rewriting sources + sprite + glyphs).
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm add maplibre-tilepackage-protocol
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Import (ESM)
|
|
12
19
|
|
|
13
20
|
```js
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
"sources": {
|
|
20
|
-
"example_source": {
|
|
21
|
-
"type": "raster",
|
|
22
|
-
"url": "tilepackage://https://example.com/example.tpkx",
|
|
23
|
-
...
|
|
21
|
+
import {
|
|
22
|
+
Protocol,
|
|
23
|
+
FileSource,
|
|
24
|
+
TilePackage,
|
|
25
|
+
} from "maplibre-tilepackage-protocol";
|
|
24
26
|
```
|
|
25
27
|
|
|
26
|
-
## TPKX
|
|
28
|
+
## Quick Start (Remote Raster TPKX)
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
```js
|
|
31
|
+
const protocol = new Protocol();
|
|
32
|
+
maplibregl.addProtocol("tilepackage", protocol.package);
|
|
33
|
+
|
|
34
|
+
const style = {
|
|
35
|
+
version: 8,
|
|
36
|
+
sources: {
|
|
37
|
+
raster: {
|
|
38
|
+
type: "raster",
|
|
39
|
+
url: "tilepackage://https://example.com/data/example.tpkx",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
layers: [{ id: "raster", type: "raster", source: "raster" }],
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
new maplibregl.Map({ container: "map", style });
|
|
46
|
+
```
|
|
29
47
|
|
|
30
|
-
|
|
48
|
+
Equivalent explicit tiles form:
|
|
31
49
|
|
|
32
|
-
|
|
50
|
+
```js
|
|
51
|
+
tiles: ["tilepackage://https://example.com/data/example.tpkx/{z}/{x}/{y}"];
|
|
52
|
+
```
|
|
33
53
|
|
|
34
|
-
|
|
54
|
+
## Local File VTPK
|
|
35
55
|
|
|
36
56
|
```js
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
});
|
|
46
|
-
}
|
|
57
|
+
const protocol = new Protocol({ debug: true });
|
|
58
|
+
maplibregl.addProtocol("tilepackage", protocol.package);
|
|
59
|
+
|
|
60
|
+
async function initFromFile(file) {
|
|
61
|
+
const pkg = new TilePackage(new FileSource(file)); // coverageCheck defaults ON
|
|
62
|
+
protocol.add(pkg); // register so sprite/glyph URLs resolve
|
|
63
|
+
const style = await pkg.getStyle();
|
|
64
|
+
new maplibregl.Map({ container: "map", style });
|
|
47
65
|
}
|
|
66
|
+
```
|
|
48
67
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
initMap(package)
|
|
68
|
+
On HTTP(S) you can instead point a style source to a relative URL:
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
url: "tilepackage://./data/archive.vtpk";
|
|
54
72
|
```
|
|
55
73
|
|
|
56
|
-
|
|
74
|
+
## Vector Style Rewriting
|
|
75
|
+
|
|
76
|
+
`TilePackage#getStyle()` for VTPK replaces any `url` with a `tiles` array (`tilepackage://<key>/{z}/{x}/{y}`), and sets `sprite` & `glyphs` to protocol endpoints. This avoids extra TileJSON requests that fail under `file://`.
|
|
77
|
+
|
|
78
|
+
## Indexed Pyramids & Overzoom Fallback
|
|
79
|
+
|
|
80
|
+
Some VTPK archives have variable depth (gaps). Missing higher-zoom tiles are automatically synthesized from a parent using an internal subdivision algorithm when a coverage map (`tilemap/root.json`) is present.
|
|
81
|
+
|
|
82
|
+
Behavior:
|
|
83
|
+
|
|
84
|
+
- Parent search ascends until a node with value `1` in the coverage map.
|
|
85
|
+
- The parent vector tile is decoded, features clipped/scaled, and re-encoded to PBF.
|
|
86
|
+
- Generated tiles are cached (`SharedPromiseCache.subdivided`) to avoid repeat work.
|
|
87
|
+
|
|
88
|
+
Disable subdivision by constructing the package with `coverageCheck:false`:
|
|
57
89
|
|
|
58
90
|
```js
|
|
59
|
-
|
|
60
|
-
errorOnMissingTile: true,
|
|
61
|
-
});
|
|
91
|
+
const pkg = new TilePackage(new FileSource(file), { coverageCheck: false });
|
|
62
92
|
```
|
|
63
93
|
|
|
64
|
-
|
|
94
|
+
If you prefer MapLibre's default empty tile behavior (no lower-zoom retention) you can set protocol option `errorOnMissingTile:true` to raise errors for missing PBF tiles.
|
|
95
|
+
|
|
96
|
+
### Caching
|
|
97
|
+
|
|
98
|
+
Overzoomed tiles are stored in-memory for the session. A simple size-based prune removes half of entries when exceeding `maxCacheEntries * 2`. (Future: LRU + byte-size thresholds.) Subdivision will be skipped entirely if the zoom delta exceeds the hard cap `maxDz` (default `8`).
|
|
99
|
+
|
|
100
|
+
### Performance Notes
|
|
101
|
+
|
|
102
|
+
- Large zoom jumps (high `dz`) cost more CPU; consider constraining user zoom range.
|
|
103
|
+
- Subdivision adds latency only on first request; subsequent hits are served from cache.
|
|
104
|
+
- Disable with `coverageCheck:false` for pure flat packages when you do not want synthesis.
|
|
105
|
+
- Tune with `maxDz` (e.g. set `maxDz:4`) to limit deep subdivision while allowing shallow overzoom.
|
|
106
|
+
|
|
107
|
+
## API Summary
|
|
108
|
+
|
|
109
|
+
- `new TilePackage(source, { coverageCheck, maxDz })` – `source` is URL string or `FileSource`. `coverageCheck` defaults to `true` enabling coverage map + overzoom; `maxDz` (default `8`) hard‑caps subdivision depth.
|
|
110
|
+
- `TilePackage#getHeader()` – name, zooms, bounds, tile type.
|
|
111
|
+
- `TilePackage#getStyle()` – raster style (TPKX) or rewritten vector style (VTPK).
|
|
112
|
+
- `TilePackage#getZxy(z,x,y)` – raw tile bytes (PBF or raster image ArrayBuffer).
|
|
113
|
+
- `Protocol.add(pkg)` – register local file-backed packages for glyph/sprite resolution.
|
|
114
|
+
- `Protocol` options: `metadata`, `errorOnMissingTile`, `debug`.
|
|
115
|
+
|
|
116
|
+
## Debug Logging
|
|
117
|
+
|
|
118
|
+
Enable `debug:true` in `Protocol` for tile fetch + instance events. Coverage ascent & subdivision messages use `[tilepackage coverage]` and `[tilepackage subdivide]` prefixes.
|
|
119
|
+
|
|
120
|
+
## Demo
|
|
121
|
+
|
|
122
|
+
The `example/` directory demonstrates local file selection, remote/relative URL input, auto-load of a demo archive, and overzoom fallback.
|
|
123
|
+
|
|
124
|
+
## TPKX Notes
|
|
125
|
+
|
|
126
|
+
TPKX contains a full raster pyramid; no style synthesis beyond setting a raster source.
|
|
127
|
+
|
|
128
|
+
## VTPK Notes
|
|
129
|
+
|
|
130
|
+
Flat and indexed VTPK archives are supported. Indexed packages rely on the overzoom fallback described above for visual continuity.
|
|
65
131
|
|
|
66
|
-
|
|
132
|
+
## Sample Data
|
|
67
133
|
|
|
68
|
-
|
|
134
|
+
Austria indexed VTPK sample:
|
|
135
|
+
https://cdn.basemap.at/offline/bmapv_vtpk_3857.vtpk
|
|
69
136
|
|
|
70
|
-
|
|
137
|
+
There is also a small example file in the example folder, and there is an online version of the example available here:
|
|
138
|
+
https://spatialillusions.com/maplibre-tilepackage-protocol/
|
|
71
139
|
|
|
72
|
-
|
|
140
|
+
## Acknowledgement
|
|
73
141
|
|
|
74
|
-
|
|
142
|
+
Inspired by concepts from PMTiles protocol (Protomaps LLC).
|
|
75
143
|
|
|
76
|
-
|
|
144
|
+
## Support
|
|
77
145
|
|
|
78
|
-
If
|
|
146
|
+
If this project helps you, consider supporting: https://buymeacoffee.com/spatialillusion
|