isard 1.0.0 → 1.2.0
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/CHANGELOG.md +51 -0
- package/dist/{basemaps.d.ts → basemap/basemaps.d.ts} +3 -3
- package/dist/{basemaps.js → basemap/basemaps.js} +3 -3
- package/dist/basemap/basemaps.js.map +1 -0
- package/dist/{grid.d.ts → basemap/grid.d.ts} +6 -6
- package/dist/{grid.js → basemap/grid.js} +61 -67
- package/dist/basemap/grid.js.map +1 -0
- package/dist/{mvt.d.ts → basemap/mvt.d.ts} +1 -1
- package/dist/{mvt.js → basemap/mvt.js} +6 -6
- package/dist/basemap/mvt.js.map +1 -0
- package/dist/{pmtiles.d.ts → basemap/pmtiles.d.ts} +16 -10
- package/dist/{pmtiles.js → basemap/pmtiles.js} +41 -33
- package/dist/basemap/pmtiles.js.map +1 -0
- package/dist/{resample.d.ts → basemap/resample.d.ts} +11 -2
- package/dist/{resample.js → basemap/resample.js} +18 -16
- package/dist/basemap/resample.js.map +1 -0
- package/dist/{terrain.d.ts → basemap/terrain.d.ts} +3 -3
- package/dist/{terrain.js → basemap/terrain.js} +7 -7
- package/dist/basemap/terrain.js.map +1 -0
- package/dist/{vectorstyle.d.ts → basemap/vectorstyle.d.ts} +12 -10
- package/dist/{vectorstyle.js → basemap/vectorstyle.js} +129 -111
- package/dist/basemap/vectorstyle.js.map +1 -0
- package/dist/{vectortiles.d.ts → basemap/vectortiles.d.ts} +18 -18
- package/dist/{vectortiles.js → basemap/vectortiles.js} +157 -109
- package/dist/basemap/vectortiles.js.map +1 -0
- package/dist/{wmts.d.ts → basemap/wmts.d.ts} +3 -3
- package/dist/{wmts.js → basemap/wmts.js} +19 -14
- package/dist/basemap/wmts.js.map +1 -0
- package/dist/basemap.worker.js +2 -2
- package/dist/basemap.worker.js.map +14 -13
- package/dist/bind/layers.d.ts +46 -0
- package/dist/bind/layers.js +154 -0
- package/dist/bind/layers.js.map +1 -0
- package/dist/{crs.d.ts → data/crs.d.ts} +11 -11
- package/dist/{crs.js → data/crs.js} +38 -34
- package/dist/data/crs.js.map +1 -0
- package/dist/{gpx.d.ts → data/gpx.d.ts} +2 -2
- package/dist/{gpx.js → data/gpx.js} +20 -20
- package/dist/data/gpx.js.map +1 -0
- package/dist/{kml.d.ts → data/kml.d.ts} +2 -2
- package/dist/{kml.js → data/kml.js} +42 -39
- package/dist/data/kml.js.map +1 -0
- package/dist/{topojson.d.ts → data/topojson.d.ts} +2 -2
- package/dist/{topojson.js → data/topojson.js} +15 -10
- package/dist/data/topojson.js.map +1 -0
- package/dist/{xml.d.ts → data/xml.d.ts} +5 -5
- package/dist/{xml.js → data/xml.js} +19 -18
- package/dist/data/xml.js.map +1 -0
- package/dist/decoder.worker.js +4 -4
- package/dist/decoder.worker.js.map +7 -7
- package/dist/{decoders.d.ts → engine/decoders.d.ts} +3 -3
- package/dist/{decoders.js → engine/decoders.js} +28 -25
- package/dist/engine/decoders.js.map +1 -0
- package/dist/{loader.d.ts → engine/loader.d.ts} +1 -1
- package/dist/{loader.js → engine/loader.js} +17 -14
- package/dist/engine/loader.js.map +1 -0
- package/dist/{protocol.d.ts → engine/protocol.d.ts} +1 -1
- package/dist/engine/protocol.js +3 -0
- package/dist/engine/protocol.js.map +1 -0
- package/dist/{requests.d.ts → engine/requests.d.ts} +1 -1
- package/dist/{requests.js → engine/requests.js} +19 -16
- package/dist/engine/requests.js.map +1 -0
- package/dist/engine-loader.d.ts +13 -9
- package/dist/engine-loader.js +30 -30
- package/dist/engine-loader.js.map +1 -1
- package/dist/formats.d.ts +3 -3
- package/dist/formats.js +3 -3
- package/dist/formats.js.map +1 -1
- package/dist/geoplateforme.d.ts +13 -13
- package/dist/geoplateforme.js +23 -21
- package/dist/geoplateforme.js.map +1 -1
- package/dist/index.d.ts +30 -29
- package/dist/index.js +18 -18
- package/dist/index.js.map +1 -1
- package/dist/isard_bg.wasm +0 -0
- package/dist/isard_core_bg.wasm +0 -0
- package/dist/isard_points_bg.wasm +0 -0
- package/dist/{extrusions.d.ts → layers/extrusions.d.ts} +1 -1
- package/dist/{extrusions.js → layers/extrusions.js} +10 -5
- package/dist/layers/extrusions.js.map +1 -0
- package/dist/{features.d.ts → layers/features.d.ts} +10 -10
- package/dist/{features.js → layers/features.js} +44 -45
- package/dist/layers/features.js.map +1 -0
- package/dist/{glyphs.d.ts → layers/glyphs.d.ts} +6 -6
- package/dist/{glyphs.js → layers/glyphs.js} +45 -41
- package/dist/layers/glyphs.js.map +1 -0
- package/dist/{icons.d.ts → layers/icons.d.ts} +10 -10
- package/dist/{icons.js → layers/icons.js} +84 -69
- package/dist/layers/icons.js.map +1 -0
- package/dist/{layers.d.ts → layers/layers.d.ts} +9 -4
- package/dist/{layers.js → layers/layers.js} +35 -31
- package/dist/layers/layers.js.map +1 -0
- package/dist/{panoramas.d.ts → layers/panoramas.d.ts} +3 -3
- package/dist/{panoramas.js → layers/panoramas.js} +54 -43
- package/dist/layers/panoramas.js.map +1 -0
- package/dist/{pointclouds.d.ts → layers/pointclouds.d.ts} +5 -5
- package/dist/{pointclouds.js → layers/pointclouds.js} +26 -34
- package/dist/layers/pointclouds.js.map +1 -0
- package/dist/{symbols.d.ts → layers/symbols.d.ts} +3 -3
- package/dist/{symbols.js → layers/symbols.js} +69 -72
- package/dist/layers/symbols.js.map +1 -0
- package/dist/map/basemap-layers.d.ts +26 -0
- package/dist/map/basemap-layers.js +61 -0
- package/dist/map/basemap-layers.js.map +1 -0
- package/dist/map/canvas.d.ts +17 -0
- package/dist/map/canvas.js +56 -0
- package/dist/map/canvas.js.map +1 -0
- package/dist/map/checks.d.ts +11 -0
- package/dist/map/checks.js +39 -0
- package/dist/map/checks.js.map +1 -0
- package/dist/map/credits.d.ts +17 -0
- package/dist/map/credits.js +34 -0
- package/dist/map/credits.js.map +1 -0
- package/dist/map/engine-settings.d.ts +15 -0
- package/dist/map/engine-settings.js +45 -0
- package/dist/map/engine-settings.js.map +1 -0
- package/dist/map/engines.d.ts +41 -0
- package/dist/map/engines.js +77 -0
- package/dist/map/engines.js.map +1 -0
- package/dist/map/events.d.ts +14 -0
- package/dist/map/events.js +46 -0
- package/dist/map/events.js.map +1 -0
- package/dist/map/frame-loop.d.ts +61 -0
- package/dist/map/frame-loop.js +139 -0
- package/dist/map/frame-loop.js.map +1 -0
- package/dist/map/hover-pick.d.ts +30 -0
- package/dist/map/hover-pick.js +56 -0
- package/dist/map/hover-pick.js.map +1 -0
- package/dist/map/layer-spec.d.ts +42 -0
- package/dist/map/layer-spec.js +34 -0
- package/dist/map/layer-spec.js.map +1 -0
- package/dist/map/layer-stack.d.ts +36 -0
- package/dist/map/layer-stack.js +101 -0
- package/dist/map/layer-stack.js.map +1 -0
- package/dist/map/overlay-host.d.ts +36 -0
- package/dist/map/overlay-host.js +101 -0
- package/dist/map/overlay-host.js.map +1 -0
- package/dist/map/panorama-host.d.ts +5 -0
- package/dist/map/panorama-host.js +32 -0
- package/dist/map/panorama-host.js.map +1 -0
- package/dist/map/raster-source.d.ts +11 -0
- package/dist/map/raster-source.js +26 -0
- package/dist/map/raster-source.js.map +1 -0
- package/dist/map/symbol-atlases.d.ts +26 -0
- package/dist/map/symbol-atlases.js +59 -0
- package/dist/map/symbol-atlases.js.map +1 -0
- package/dist/map/viewshed.d.ts +5 -0
- package/dist/map/viewshed.js +28 -0
- package/dist/map/viewshed.js.map +1 -0
- package/dist/map/workers.d.ts +46 -0
- package/dist/map/workers.js +73 -0
- package/dist/map/workers.js.map +1 -0
- package/dist/map.d.ts +46 -127
- package/dist/map.js +183 -698
- package/dist/map.js.map +1 -1
- package/dist/projections.d.ts +3 -3
- package/dist/projections.js +2 -2
- package/dist/projections.js.map +1 -1
- package/dist/react/Control.d.ts +11 -0
- package/dist/react/Control.js +18 -0
- package/dist/react/Control.js.map +1 -0
- package/dist/react/CustomLayer.d.ts +11 -0
- package/dist/react/CustomLayer.js +30 -0
- package/dist/react/CustomLayer.js.map +1 -0
- package/dist/react/IsardMap.d.ts +43 -0
- package/dist/react/IsardMap.js +146 -0
- package/dist/react/IsardMap.js.map +1 -0
- package/dist/react/Layer.d.ts +42 -0
- package/dist/react/Layer.js +74 -0
- package/dist/react/Layer.js.map +1 -0
- package/dist/react/Marker.d.ts +24 -0
- package/dist/react/Marker.js +53 -0
- package/dist/react/Marker.js.map +1 -0
- package/dist/react/Panel.d.ts +11 -0
- package/dist/react/Panel.js +37 -0
- package/dist/react/Panel.js.map +1 -0
- package/dist/react/Popup.d.ts +18 -0
- package/dist/react/Popup.js +60 -0
- package/dist/react/Popup.js.map +1 -0
- package/dist/react/Swipe.d.ts +9 -0
- package/dist/react/Swipe.js +41 -0
- package/dist/react/Swipe.js.map +1 -0
- package/dist/react/Viewshed.d.ts +5 -0
- package/dist/react/Viewshed.js +28 -0
- package/dist/react/Viewshed.js.map +1 -0
- package/dist/react/context.d.ts +32 -0
- package/dist/react/context.js +20 -0
- package/dist/react/context.js.map +1 -0
- package/dist/react/index.d.ts +26 -0
- package/dist/react/index.js +22 -0
- package/dist/react/index.js.map +1 -0
- package/dist/settings.d.ts +6 -10
- package/dist/settings.js +19 -17
- package/dist/settings.js.map +1 -1
- package/dist/types.d.ts +8 -8
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/dist/{controls.d.ts → ui/controls.d.ts} +1 -1
- package/dist/{controls.js → ui/controls.js} +6 -4
- package/dist/ui/controls.js.map +1 -0
- package/dist/{interaction.d.ts → ui/interaction.d.ts} +9 -5
- package/dist/{interaction.js → ui/interaction.js} +9 -8
- package/dist/ui/interaction.js.map +1 -0
- package/dist/{overlay.d.ts → ui/overlay.d.ts} +2 -2
- package/dist/{overlay.js → ui/overlay.js} +18 -20
- package/dist/ui/overlay.js.map +1 -0
- package/dist/{style.d.ts → ui/style.d.ts} +1 -1
- package/dist/{style.js → ui/style.js} +2 -2
- package/dist/ui/style.js.map +1 -0
- package/dist/{animation.d.ts → util/animation.d.ts} +9 -5
- package/dist/{animation.js → util/animation.js} +6 -6
- package/dist/util/animation.js.map +1 -0
- package/dist/{color.d.ts → util/color.d.ts} +1 -1
- package/dist/{color.js → util/color.js} +14 -16
- package/dist/util/color.js.map +1 -0
- package/dist/{geo.d.ts → util/geo.d.ts} +6 -6
- package/dist/{geo.js → util/geo.js} +12 -12
- package/dist/util/geo.js.map +1 -0
- package/dist/util/guards.d.ts +7 -0
- package/dist/util/guards.js +8 -0
- package/dist/util/guards.js.map +1 -0
- package/dist/util/lru.js.map +1 -0
- package/dist/wasm/isard.d.ts +168 -0
- package/dist/wasm/isard.js +146 -0
- package/dist/wasm/isard_core.d.ts +144 -0
- package/dist/wasm/isard_core.js +122 -0
- package/dist/{basemap.worker.d.ts → workers/basemap.worker.d.ts} +17 -7
- package/dist/workers/basemap.worker.js +658 -0
- package/dist/workers/basemap.worker.js.map +1 -0
- package/package.json +24 -1
- package/vite.js +1 -1
- package/dist/animation.js.map +0 -1
- package/dist/basemaps.js.map +0 -1
- package/dist/color.js.map +0 -1
- package/dist/controls.js.map +0 -1
- package/dist/crs.js.map +0 -1
- package/dist/decoders.js.map +0 -1
- package/dist/extrusions.js.map +0 -1
- package/dist/features.js.map +0 -1
- package/dist/geo.js.map +0 -1
- package/dist/glyphs.js.map +0 -1
- package/dist/gpx.js.map +0 -1
- package/dist/grid.js.map +0 -1
- package/dist/icons.js.map +0 -1
- package/dist/interaction.js.map +0 -1
- package/dist/kml.js.map +0 -1
- package/dist/layers.js.map +0 -1
- package/dist/loader.js.map +0 -1
- package/dist/lru.js.map +0 -1
- package/dist/mvt.js.map +0 -1
- package/dist/overlay.js.map +0 -1
- package/dist/panoramas.js.map +0 -1
- package/dist/pmtiles.js.map +0 -1
- package/dist/pointclouds.js.map +0 -1
- package/dist/protocol.js +0 -2
- package/dist/protocol.js.map +0 -1
- package/dist/requests.js.map +0 -1
- package/dist/resample.js.map +0 -1
- package/dist/style.js.map +0 -1
- package/dist/symbols.js.map +0 -1
- package/dist/terrain.js.map +0 -1
- package/dist/topojson.js.map +0 -1
- package/dist/vectorstyle.js.map +0 -1
- package/dist/vectortiles.js.map +0 -1
- package/dist/wmts.js.map +0 -1
- package/dist/xml.js.map +0 -1
- /package/dist/{lru.d.ts → util/lru.d.ts} +0 -0
- /package/dist/{lru.js → util/lru.js} +0 -0
|
@@ -1,13 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vector basemaps from a MapLibre style (OpenFreeMap's Positron by default): the fills, lines, circles and raster
|
|
3
|
+
* layers drawn tile by tile in workers into the raster pool, so that they lie on the relief like any basemap and
|
|
4
|
+
* composite with the hillshade in one pass; and the labels of the style's symbol layers in a symbol layer of their own,
|
|
5
|
+
* kept above the application's layers (as MapLibre's `beforeId: firstSymbol` does), listed by the workers, shaped in
|
|
6
|
+
* the page once per vector tile, placed by the engine.
|
|
7
|
+
*
|
|
8
|
+
* Any subset of the style can be drawn on its own raster layer (`raster({ layers })`), at its own place in the stack:
|
|
9
|
+
* rivers from the basemap's data over a flood layer, for instance, restyled with `extraLayers`.
|
|
10
|
+
*/
|
|
11
|
+
import { headerRules, onHeaderRules, withHeaders } from "../engine/requests.js";
|
|
12
|
+
import { assetUrl } from "../engine-loader.js";
|
|
13
|
+
import { IGN_ATTRIBUTION } from "../geoplateforme.js";
|
|
14
|
+
import { loadSprites, readPixels } from "../layers/icons.js";
|
|
15
|
+
import { mercatorX, mercatorY } from "../util/geo.js";
|
|
16
|
+
import { isRecord } from "../util/guards.js";
|
|
17
|
+
import { Lru } from "../util/lru.js";
|
|
1
18
|
import { OPENFREEMAP_ATTRIBUTION } from "./basemaps.js";
|
|
2
|
-
import { assetUrl } from "./engine-loader.js";
|
|
3
|
-
import { mercatorX, mercatorY } from "./geo.js";
|
|
4
|
-
import { IGN_ATTRIBUTION } from "./geoplateforme.js";
|
|
5
|
-
import { loadSprites, readPixels } from "./icons.js";
|
|
6
|
-
import { Lru } from "./lru.js";
|
|
7
19
|
import { pmtiles, pmtilesUrl } from "./pmtiles.js";
|
|
8
|
-
import { headerRules, onHeaderRules, withHeaders } from "./requests.js";
|
|
9
20
|
import { SOURCE_CACHE } from "./resample.js";
|
|
10
|
-
import { labelFont, } from "./vectorstyle.js";
|
|
21
|
+
import { isStyle, labelFont, } from "./vectorstyle.js";
|
|
11
22
|
/** OpenFreeMap's styles: OpenStreetMap data in the OpenMapTiles schema, worldwide, free and without a key */
|
|
12
23
|
export const OPENFREEMAP_STYLES = {
|
|
13
24
|
positron: 'https://tiles.openfreemap.org/styles/positron',
|
|
@@ -28,43 +39,75 @@ export const VECTOR_BASEMAPS = {
|
|
|
28
39
|
'ign-plan-grey-vector': PLAN_STYLES.grey,
|
|
29
40
|
};
|
|
30
41
|
/** The credits of a known style: OpenFreeMap's, PLAN.IGN's */
|
|
31
|
-
export
|
|
42
|
+
export const styleAttribution = (style) => {
|
|
32
43
|
if (typeof style !== 'string')
|
|
33
44
|
return undefined;
|
|
34
|
-
if (Object.values(OPENFREEMAP_STYLES).
|
|
45
|
+
if (Object.values(OPENFREEMAP_STYLES).some((s) => s === style))
|
|
35
46
|
return OPENFREEMAP_ATTRIBUTION;
|
|
36
|
-
if (Object.values(PLAN_STYLES).
|
|
47
|
+
if (Object.values(PLAN_STYLES).some((s) => s === style))
|
|
37
48
|
return IGN_ATTRIBUTION;
|
|
38
49
|
return undefined;
|
|
39
|
-
}
|
|
50
|
+
};
|
|
40
51
|
/** Text or icon size of a style (a number, legacy stops, or the stops of a zoom expression made by the worker) as a
|
|
41
52
|
* size for the symbol layer */
|
|
42
|
-
export
|
|
53
|
+
export const size = (value, fallback = 16) => {
|
|
54
|
+
const stop = (s) => {
|
|
55
|
+
const [z, v] = Array.isArray(s) ? s : [];
|
|
56
|
+
return [Number(z), Number(v)];
|
|
57
|
+
};
|
|
43
58
|
if (typeof value === 'number')
|
|
44
59
|
return value;
|
|
45
|
-
if (Array.isArray(value) && value.length > 0 && value.every(Array.isArray))
|
|
46
|
-
return value.map(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return value.stops.map((s) => {
|
|
50
|
-
const [z, v] = s;
|
|
51
|
-
return [Number(z), Number(v)];
|
|
52
|
-
});
|
|
53
|
-
}
|
|
60
|
+
if (Array.isArray(value) && value.length > 0 && value.every(Array.isArray))
|
|
61
|
+
return value.map(stop);
|
|
62
|
+
if (isRecord(value) && Array.isArray(value.stops))
|
|
63
|
+
return value.stops.map(stop);
|
|
54
64
|
return fallback;
|
|
55
|
-
}
|
|
65
|
+
};
|
|
66
|
+
/** The anchors of the symbol layer */
|
|
67
|
+
const ANCHORS = new Set([
|
|
68
|
+
'center',
|
|
69
|
+
'top',
|
|
70
|
+
'bottom',
|
|
71
|
+
'left',
|
|
72
|
+
'right',
|
|
73
|
+
'top-left',
|
|
74
|
+
'top-right',
|
|
75
|
+
'bottom-left',
|
|
76
|
+
'bottom-right',
|
|
77
|
+
]);
|
|
78
|
+
const isAnchor = (value) => value !== undefined && ANCHORS.has(value);
|
|
79
|
+
/** A style's anchor (`text-anchor`, `icon-anchor`) for the symbol layer: `center` if it is none */
|
|
80
|
+
const anchor = (value) => (isAnchor(value) ? value : 'center');
|
|
56
81
|
/** Fetches a JSON document (a style, a TileJSON) */
|
|
57
|
-
async
|
|
82
|
+
const json = async (url) => {
|
|
58
83
|
const response = await fetch(url, withHeaders(url));
|
|
59
84
|
if (!response.ok)
|
|
60
85
|
throw new Error(`${url}: ${response.status}`);
|
|
61
|
-
return
|
|
62
|
-
}
|
|
86
|
+
return response.json();
|
|
87
|
+
};
|
|
88
|
+
/** A style fetched: a MapLibre style, or an error */
|
|
89
|
+
const fetchStyle = async (url) => {
|
|
90
|
+
const style = await json(url);
|
|
91
|
+
if (!isStyle(style))
|
|
92
|
+
throw new Error(`${url}: not a MapLibre style`);
|
|
93
|
+
return style;
|
|
94
|
+
};
|
|
95
|
+
const isTileJson = (value) => isRecord(value) &&
|
|
96
|
+
Array.isArray(value.tiles) &&
|
|
97
|
+
value.tiles.every((t) => typeof t === 'string') &&
|
|
98
|
+
(value.maxzoom === undefined || typeof value.maxzoom === 'number');
|
|
99
|
+
/** A TileJSON fetched, or an error */
|
|
100
|
+
const fetchTileJson = async (url) => {
|
|
101
|
+
const tilejson = await json(url);
|
|
102
|
+
if (!isTileJson(tilejson))
|
|
103
|
+
throw new Error(`${url}: not a TileJSON`);
|
|
104
|
+
return tilejson;
|
|
105
|
+
};
|
|
63
106
|
/**
|
|
64
107
|
* A style source's tiles and deepest level: a `pmtiles://` archive (its `url`, or a `tiles` template) read for its
|
|
65
108
|
* header, its tiles then named `pmtiles://<absolute archive URL>/{z}/{x}/{y}` for the workers; other sources as they are
|
|
66
109
|
*/
|
|
67
|
-
async
|
|
110
|
+
const resolveSource = async (source) => {
|
|
68
111
|
const given = source.url ?? source.tiles?.[0] ?? '';
|
|
69
112
|
const archive = pmtilesUrl(given.replace(/\/\{z\}\/\{x\}\/\{y\}$/, ''));
|
|
70
113
|
if (!archive)
|
|
@@ -74,20 +117,20 @@ async function resolveSource(source) {
|
|
|
74
117
|
};
|
|
75
118
|
const header = await pmtiles(archive).header();
|
|
76
119
|
return { tiles: [`pmtiles://${archive}/{z}/{x}/{y}`], maxzoom: source.maxzoom ?? header.maxZoom };
|
|
77
|
-
}
|
|
120
|
+
};
|
|
78
121
|
/** Pause before the labels of tiles that failed are asked for again, when no move brings an update (ms) */
|
|
79
122
|
const RETRY_LABELS_MS = 3000;
|
|
80
123
|
/** Default size of a basemap worker pool: cores - 1, 1 to 4 */
|
|
81
|
-
export
|
|
124
|
+
export const defaultWorkerCount = () => {
|
|
82
125
|
return Math.min(4, Math.max(1, (typeof navigator !== 'undefined' ? navigator.hardwareConcurrency || 2 : 2) - 1));
|
|
83
|
-
}
|
|
126
|
+
};
|
|
84
127
|
/** Default URL of the basemap worker: in the page's assets folder (`isard/vite`), else next to the module */
|
|
85
|
-
export
|
|
128
|
+
export const defaultWorkerUrl = (assetsUrl) => {
|
|
86
129
|
return assetUrl('basemap.worker.js', undefined, assetsUrl);
|
|
87
|
-
}
|
|
130
|
+
};
|
|
88
131
|
/** Fetch priority of a raster tile drawn by the workers: 'high' near the center of the view, at the current zoom or
|
|
89
132
|
* coarser; 'low' far from it or finer (prefetch); 'auto' between */
|
|
90
|
-
export
|
|
133
|
+
export const tilePriority = (z, x, y, camera) => {
|
|
91
134
|
// A raster tile of level z covers the map at zoom z - 1
|
|
92
135
|
if (z - 1 > camera.zoom + 1)
|
|
93
136
|
return 'low';
|
|
@@ -96,22 +139,22 @@ export function tilePriority(z, x, y, camera) {
|
|
|
96
139
|
const cx = mercatorX(lon) * n;
|
|
97
140
|
const cy = mercatorY(lat) * n;
|
|
98
141
|
// Across the antimeridian, the short way
|
|
99
|
-
|
|
100
|
-
dx = Math.min(
|
|
142
|
+
const along = Math.abs(x + 0.5 - cx) % n;
|
|
143
|
+
const dx = Math.min(along, n - along);
|
|
101
144
|
const d = Math.hypot(dx, y + 0.5 - cy);
|
|
102
145
|
if (d <= 1.5)
|
|
103
146
|
return 'high';
|
|
104
147
|
return d >= 4 ? 'low' : 'auto';
|
|
105
|
-
}
|
|
148
|
+
};
|
|
106
149
|
/** The worker of a vector tile among `count`: always the same one */
|
|
107
|
-
export
|
|
150
|
+
export const workerIndex = (vz, vx, vy, count) => {
|
|
108
151
|
// Unsigned: every worker gets its share
|
|
109
152
|
return ((Math.imul(vx, 73856093) ^ Math.imul(vy, 19349663) ^ vz) >>> 0) % Math.max(1, count);
|
|
110
|
-
}
|
|
153
|
+
};
|
|
111
154
|
/** The worker-side key of a renderer: unique across the `VectorTiles` sharing a pool */
|
|
112
|
-
export
|
|
155
|
+
export const rendererKey = (namespace, n) => {
|
|
113
156
|
return `${namespace}:r${n}`;
|
|
114
|
-
}
|
|
157
|
+
};
|
|
115
158
|
/**
|
|
116
159
|
* @internal Workers drawing vector tiles, shared by the `VectorTiles` of a map: each vector tile always goes to the
|
|
117
160
|
* same worker, which keeps it decoded for every style drawn from it. Requests are tracked one by one, with their
|
|
@@ -130,7 +173,7 @@ export class BasemapWorkers {
|
|
|
130
173
|
constructor(count, url, create = (u) => new Worker(u, { type: 'module' })) {
|
|
131
174
|
this.count = count;
|
|
132
175
|
this.url = url;
|
|
133
|
-
|
|
176
|
+
const start = () => {
|
|
134
177
|
const worker = create(url);
|
|
135
178
|
worker.onmessage = ({ data }) => {
|
|
136
179
|
const p = this.pending.get(data.id);
|
|
@@ -152,10 +195,12 @@ export class BasemapWorkers {
|
|
|
152
195
|
if (rules.length > 0)
|
|
153
196
|
worker.postMessage({ type: 'headers', rules });
|
|
154
197
|
return worker;
|
|
155
|
-
}
|
|
198
|
+
};
|
|
199
|
+
this.workers = [start(), ...Array.from({ length: Math.max(1, count) - 1 }, start)];
|
|
156
200
|
this.unfollow = onHeaderRules((rules) => {
|
|
157
|
-
|
|
201
|
+
this.workers.forEach((w) => {
|
|
158
202
|
w.postMessage({ type: 'headers', rules });
|
|
203
|
+
});
|
|
159
204
|
});
|
|
160
205
|
}
|
|
161
206
|
/** A prefix for the renderer keys of one `VectorTiles` */
|
|
@@ -169,12 +214,12 @@ export class BasemapWorkers {
|
|
|
169
214
|
/** Rejects the requests of a failed worker */
|
|
170
215
|
fail(worker, message) {
|
|
171
216
|
const error = new Error(`isard: ${message}. If a bundler moves the worker, give its URL in the \`basemapWorkerUrl\` option (see "With a bundler" in the guide)`);
|
|
172
|
-
|
|
217
|
+
this.pending.forEach((p, id) => {
|
|
173
218
|
if (p.worker !== worker)
|
|
174
|
-
|
|
219
|
+
return;
|
|
175
220
|
this.pending.delete(id);
|
|
176
221
|
p.reject(error);
|
|
177
|
-
}
|
|
222
|
+
});
|
|
178
223
|
}
|
|
179
224
|
/** The worker of a vector tile */
|
|
180
225
|
worker(vz, vx, vy) {
|
|
@@ -187,8 +232,9 @@ export class BasemapWorkers {
|
|
|
187
232
|
// A renderer tells the workers how many they are: they share the decoded tiles' budget
|
|
188
233
|
const sent = message.type === 'init' ? { ...message, workers: this.workers.length } : message;
|
|
189
234
|
// A sprite image is copied to each worker (structured clone)
|
|
190
|
-
|
|
235
|
+
this.workers.forEach((w) => {
|
|
191
236
|
w.postMessage(sent);
|
|
237
|
+
});
|
|
192
238
|
}
|
|
193
239
|
/** Asks a worker for a tile's image or labels, on behalf of `owner` */
|
|
194
240
|
request(worker, work, owner, signal) {
|
|
@@ -237,13 +283,13 @@ export class BasemapWorkers {
|
|
|
237
283
|
}
|
|
238
284
|
/** Cancels the requests of an owner (the workers stop them) */
|
|
239
285
|
cancel(owner) {
|
|
240
|
-
|
|
286
|
+
this.pending.forEach((p, id) => {
|
|
241
287
|
if (p.owner !== owner)
|
|
242
|
-
|
|
288
|
+
return;
|
|
243
289
|
this.pending.delete(id);
|
|
244
290
|
p.worker.postMessage({ type: 'abort', id });
|
|
245
291
|
p.reject(new DOMException('isard: vector tiles destroyed', 'AbortError'));
|
|
246
|
-
}
|
|
292
|
+
});
|
|
247
293
|
}
|
|
248
294
|
/** Stops the workers; their requests fail */
|
|
249
295
|
terminate() {
|
|
@@ -251,18 +297,20 @@ export class BasemapWorkers {
|
|
|
251
297
|
return;
|
|
252
298
|
this.terminated = true;
|
|
253
299
|
this.unfollow();
|
|
254
|
-
|
|
300
|
+
this.workers.forEach((w) => {
|
|
255
301
|
w.terminate();
|
|
302
|
+
});
|
|
256
303
|
const pending = [...this.pending.values()];
|
|
257
304
|
this.pending.clear();
|
|
258
|
-
|
|
305
|
+
pending.forEach((p) => {
|
|
259
306
|
p.reject(new DOMException('isard: vector tiles destroyed', 'AbortError'));
|
|
307
|
+
});
|
|
260
308
|
}
|
|
261
309
|
}
|
|
262
310
|
/** A tile's label candidates as features, by style layer */
|
|
263
|
-
export
|
|
311
|
+
export const tileLabels = (candidates) => {
|
|
264
312
|
const byLayer = new Map();
|
|
265
|
-
|
|
313
|
+
candidates.forEach((p) => {
|
|
266
314
|
const feature = {
|
|
267
315
|
type: 'Feature',
|
|
268
316
|
properties: p,
|
|
@@ -281,9 +329,9 @@ export function tileLabels(candidates) {
|
|
|
281
329
|
list.push(feature);
|
|
282
330
|
else
|
|
283
331
|
byLayer.set(p.layer, [feature]);
|
|
284
|
-
}
|
|
332
|
+
});
|
|
285
333
|
return [...byLayer].sort((a, b) => b[0] - a[0]);
|
|
286
|
-
}
|
|
334
|
+
};
|
|
287
335
|
export class VectorTiles {
|
|
288
336
|
map;
|
|
289
337
|
pool;
|
|
@@ -324,16 +372,14 @@ export class VectorTiles {
|
|
|
324
372
|
});
|
|
325
373
|
}
|
|
326
374
|
async load(input) {
|
|
327
|
-
const style = typeof input === 'string' ? await
|
|
375
|
+
const style = typeof input === 'string' ? await fetchStyle(input) : input;
|
|
328
376
|
const [name, source] = Object.entries(style.sources).find(([, s]) => s.type === 'vector') ?? [];
|
|
329
377
|
if (!name || !source)
|
|
330
378
|
throw new Error('the style has no vector source');
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
maxzoom ??= tilejson.maxzoom;
|
|
336
|
-
}
|
|
379
|
+
const resolved = await resolveSource(source);
|
|
380
|
+
const tilejson = !resolved.tiles && source.url ? await fetchTileJson(source.url) : undefined;
|
|
381
|
+
const tiles = tilejson === undefined ? resolved.tiles : tilejson.tiles;
|
|
382
|
+
const maxzoom = resolved.maxzoom ?? tilejson?.maxzoom;
|
|
337
383
|
const template = tiles?.[0];
|
|
338
384
|
if (!template)
|
|
339
385
|
throw new Error(`source ${name} has no tiles`);
|
|
@@ -357,11 +403,11 @@ export class VectorTiles {
|
|
|
357
403
|
/** The fonts of the style's labels, for its glyphs (the first of each `text-font`, as the workers take it) */
|
|
358
404
|
static fonts(style) {
|
|
359
405
|
const fonts = new Set();
|
|
360
|
-
|
|
406
|
+
style.layers.forEach((layer) => {
|
|
361
407
|
const font = layer.layout?.['text-font'];
|
|
362
408
|
if (layer.type === 'symbol' && Array.isArray(font) && typeof font[0] === 'string')
|
|
363
409
|
fonts.add(labelFont(font[0]));
|
|
364
|
-
}
|
|
410
|
+
});
|
|
365
411
|
return [...fonts];
|
|
366
412
|
}
|
|
367
413
|
/** The style's sprites (their JSON and their images), loaded once, for the fill patterns and the icons */
|
|
@@ -443,7 +489,7 @@ export class VectorTiles {
|
|
|
443
489
|
color: (p) => p.color,
|
|
444
490
|
haloColor: (p) => p.haloColor,
|
|
445
491
|
haloWidth: (p) => p.haloWidth,
|
|
446
|
-
anchor: (p) => p.anchor,
|
|
492
|
+
anchor: (p) => anchor(p.anchor),
|
|
447
493
|
offset: (p) => p.offset,
|
|
448
494
|
maxWidth: (p) => p.maxWidth,
|
|
449
495
|
lineHeight: (p) => p.lineHeight,
|
|
@@ -452,7 +498,7 @@ export class VectorTiles {
|
|
|
452
498
|
textOptional: (p) => p.textOptional === true,
|
|
453
499
|
icon: (p) => (p.icon ? this.iconPrefix + p.icon.image : ''),
|
|
454
500
|
iconSize: (p) => size(p.icon?.size ?? 1, 1),
|
|
455
|
-
iconAnchor: (p) => (p.icon?.anchor
|
|
501
|
+
iconAnchor: (p) => anchor(p.icon?.anchor),
|
|
456
502
|
iconOffset: (p) => p.icon?.offset ?? [0, 0],
|
|
457
503
|
iconRotate: (p) => p.icon?.rotate ?? 0,
|
|
458
504
|
iconRotationAlignment: (p) => p.icon?.alignment ?? 'viewport',
|
|
@@ -472,10 +518,10 @@ export class VectorTiles {
|
|
|
472
518
|
// Its icons from its sprites, before the first labels
|
|
473
519
|
const icons = style.layers.some((l) => l.type === 'symbol' && l.layout?.['icon-image'] !== undefined);
|
|
474
520
|
if (icons && style.sprite) {
|
|
475
|
-
|
|
521
|
+
(await this.loadSprites(style.sprite)).forEach((sprite) => {
|
|
476
522
|
if (!this.destroyed)
|
|
477
523
|
this.map.icons.addSprite(this.iconPrefix, sprite.icons, () => readPixels(sprite.image));
|
|
478
|
-
}
|
|
524
|
+
});
|
|
479
525
|
}
|
|
480
526
|
return this.renderer((l) => l.type === 'symbol' && layers(l), []);
|
|
481
527
|
});
|
|
@@ -500,18 +546,22 @@ export class VectorTiles {
|
|
|
500
546
|
if (ground.length > 0) {
|
|
501
547
|
// The ground's tiles, the nearest first: a tile so many levels coarser than the finest in view has its
|
|
502
548
|
// labels of a zoom as many under the view's, past the source's deepest level those of that level at the zoom
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
549
|
+
const groundTiles = Array.from({ length: Math.ceil(ground.length / 3) }, (_, k) => [
|
|
550
|
+
ground[3 * k] ?? 0,
|
|
551
|
+
ground[3 * k + 1] ?? 0,
|
|
552
|
+
ground[3 * k + 2] ?? 0,
|
|
553
|
+
]);
|
|
554
|
+
const top = groundTiles.reduce((t, [z]) => Math.max(t, z), 0);
|
|
555
|
+
groundTiles.forEach(([z, x, y]) => {
|
|
556
|
+
if (keys.length >= maxTiles)
|
|
557
|
+
return;
|
|
508
558
|
const at = Math.max(0, zoom - (top - z));
|
|
509
559
|
const tz = Math.min(at, maxzoom, z);
|
|
510
560
|
const shift = 2 ** (z - tz);
|
|
511
561
|
const key = `${tz}/${Math.floor(x / shift)}/${Math.floor(y / shift)}${at > tz ? `@${at}` : ''}`;
|
|
512
562
|
if (!keys.includes(key))
|
|
513
563
|
keys.push(key);
|
|
514
|
-
}
|
|
564
|
+
});
|
|
515
565
|
}
|
|
516
566
|
else {
|
|
517
567
|
const z = Math.min(zoom, maxzoom);
|
|
@@ -531,26 +581,22 @@ export class VectorTiles {
|
|
|
531
581
|
Math.max(0, ty(north), Math.floor(cy) - reach),
|
|
532
582
|
Math.min(n - 1, ty(south), Math.floor(cy) + reach),
|
|
533
583
|
];
|
|
534
|
-
const wanted = [];
|
|
535
|
-
for (let y = y0; y <= y1; y += 1)
|
|
536
|
-
for (let x = x0; x <= x1; x += 1)
|
|
537
|
-
wanted.push([x, y]);
|
|
584
|
+
const wanted = Array.from({ length: y1 - y0 + 1 }, (_, j) => y0 + j).flatMap((y) => Array.from({ length: x1 - x0 + 1 }, (_, i) => [x0 + i, y]));
|
|
538
585
|
// Nearest to the center first, at most `maxTiles` (tilted views reach far)
|
|
539
586
|
wanted.sort((a, b) => Math.hypot(a[0] + 0.5 - cx, a[1] + 0.5 - cy) - Math.hypot(b[0] + 0.5 - cx, b[1] + 0.5 - cy));
|
|
540
587
|
// Past the source's deepest level, its tiles' labels at the zoom of the view (the layers of the deeper zooms)
|
|
541
|
-
|
|
542
|
-
keys.push(`${z}/${x}/${y}${zoom > z ? `@${zoom}` : ''}`);
|
|
588
|
+
keys.push(...wanted.slice(0, maxTiles).map(([x, y]) => `${z}/${x}/${y}${zoom > z ? `@${zoom}` : ''}`));
|
|
543
589
|
}
|
|
544
590
|
// The same tiles as the labels shown: nothing to do
|
|
545
591
|
const set = keys.join(' ');
|
|
546
592
|
if (set === shown)
|
|
547
593
|
return;
|
|
548
594
|
const lists = await Promise.all(keys.map((k, index) => {
|
|
549
|
-
|
|
550
|
-
if (
|
|
551
|
-
return
|
|
595
|
+
const cached = tiles.get(k);
|
|
596
|
+
if (cached)
|
|
597
|
+
return cached;
|
|
552
598
|
const [tile, deeper] = k.split('@');
|
|
553
|
-
const [tz, x, y] = (tile ?? '').split('/').map(Number);
|
|
599
|
+
const [tz = 0, x = 0, y = 0] = (tile ?? '').split('/').map(Number);
|
|
554
600
|
// The nearest tiles first: the others wait for the raster tiles
|
|
555
601
|
const priority = index < 4 ? 'auto' : 'low';
|
|
556
602
|
const work = {
|
|
@@ -562,7 +608,7 @@ export class VectorTiles {
|
|
|
562
608
|
priority,
|
|
563
609
|
...(deeper === undefined ? {} : { zoom: Number(deeper) }),
|
|
564
610
|
};
|
|
565
|
-
p = this.request(tz, x, y, work).then((r) => tileLabels('labels' in r ? r.labels : []), () => {
|
|
611
|
+
const p = this.request(tz, x, y, work).then((r) => tileLabels('labels' in r ? r.labels : []), () => {
|
|
566
612
|
// A network error is not kept: the tile is asked for again on the next update
|
|
567
613
|
tiles.delete(k);
|
|
568
614
|
return [];
|
|
@@ -584,14 +630,7 @@ export class VectorTiles {
|
|
|
584
630
|
// The labels of the higher style layers first: they win the collisions; for each style layer, the tiles nearest
|
|
585
631
|
// to the center first
|
|
586
632
|
const layerIds = [...new Set(lists.flatMap((list) => list.map(([layer]) => layer)))].sort((a, b) => b - a);
|
|
587
|
-
const groups = [];
|
|
588
|
-
for (const layer of layerIds) {
|
|
589
|
-
for (const list of lists) {
|
|
590
|
-
const group = list.find(([l]) => l === layer)?.[1];
|
|
591
|
-
if (group)
|
|
592
|
-
groups.push(group);
|
|
593
|
-
}
|
|
594
|
-
}
|
|
633
|
+
const groups = layerIds.flatMap((layer) => lists.map((list) => list.find(([l]) => l === layer)?.[1]).filter((group) => group !== undefined));
|
|
595
634
|
symbol.setGroups(groups);
|
|
596
635
|
};
|
|
597
636
|
// The style failed to load: reported by `ready`
|
|
@@ -619,19 +658,22 @@ export class VectorTiles {
|
|
|
619
658
|
if (this.destroyed)
|
|
620
659
|
return;
|
|
621
660
|
this.destroyed = true;
|
|
622
|
-
|
|
661
|
+
this.cleanup.forEach((off) => {
|
|
623
662
|
off();
|
|
663
|
+
});
|
|
624
664
|
this.cleanup.length = 0;
|
|
625
|
-
|
|
665
|
+
this.layers.forEach((layer) => {
|
|
626
666
|
if (this.map.hasLayer(layer))
|
|
627
667
|
layer.remove();
|
|
668
|
+
});
|
|
628
669
|
this.layers.length = 0;
|
|
629
670
|
this.map.dropVectorTiles(this);
|
|
630
671
|
// The page's copy of the sprites (the workers have theirs), and their icons
|
|
631
672
|
this.sprites
|
|
632
673
|
?.then((sprites) => {
|
|
633
|
-
|
|
674
|
+
sprites.forEach((sprite) => {
|
|
634
675
|
sprite.image.close();
|
|
676
|
+
});
|
|
635
677
|
this.map.icons.remove(this.iconPrefix, true);
|
|
636
678
|
})
|
|
637
679
|
.catch(() => undefined);
|
|
@@ -641,8 +683,9 @@ export class VectorTiles {
|
|
|
641
683
|
else {
|
|
642
684
|
// Shared workers: only its requests stop and its renderers go
|
|
643
685
|
this.pool.cancel(this);
|
|
644
|
-
|
|
686
|
+
this.renderers.forEach((key) => {
|
|
645
687
|
this.pool.broadcast({ type: 'drop', key });
|
|
688
|
+
});
|
|
646
689
|
}
|
|
647
690
|
this.renderers.length = 0;
|
|
648
691
|
}
|
|
@@ -655,10 +698,10 @@ const BASIC_COLORS = ['#2f6fd1', '#d1495b', '#2a9d8f', '#e9a03b', '#7b5ea7', '#5
|
|
|
655
698
|
* layer, the `name` of points as labels. `source` is the style's vector source (`url`: TileJSON or `pmtiles://…`, or
|
|
656
699
|
* `tiles`)
|
|
657
700
|
*/
|
|
658
|
-
export
|
|
701
|
+
export const basicStyle = (source, layers) => {
|
|
659
702
|
const out = [];
|
|
660
703
|
layers.forEach((name, i) => {
|
|
661
|
-
const color = BASIC_COLORS[i % BASIC_COLORS.length];
|
|
704
|
+
const color = BASIC_COLORS[i % BASIC_COLORS.length] ?? '#2f6fd1';
|
|
662
705
|
const base = { source: 'data', 'source-layer': name };
|
|
663
706
|
out.push({ id: `${name}-fill`, type: 'fill', ...base, paint: { 'fill-color': color, 'fill-opacity': 0.18 } }, { id: `${name}-line`, type: 'line', ...base, paint: { 'line-color': color, 'line-width': 1.2 } }, {
|
|
664
707
|
id: `${name}-circle`,
|
|
@@ -679,21 +722,24 @@ export function basicStyle(source, layers) {
|
|
|
679
722
|
});
|
|
680
723
|
});
|
|
681
724
|
return { version: 8, sources: { data: { type: 'vector', ...source } }, layers: out };
|
|
682
|
-
}
|
|
725
|
+
};
|
|
683
726
|
/** HTML of a file reduced to its text, escaped: credits from an archive's metadata cannot run in the page */
|
|
684
|
-
|
|
727
|
+
const plainText = (html) => {
|
|
685
728
|
return html
|
|
686
729
|
.replace(/<[^>]*>/g, '')
|
|
687
730
|
.replace(/&(?!(amp|lt|gt|quot|copy|#\d+);)/g, '&')
|
|
688
731
|
.replace(/</g, '<')
|
|
689
732
|
.replace(/>/g, '>');
|
|
690
|
-
}
|
|
733
|
+
};
|
|
691
734
|
/** @internal `GeoMap.addPmtiles`: a raster layer of the archive's images, or vector tiles with their raster layer and
|
|
692
735
|
* labels */
|
|
693
|
-
export async
|
|
694
|
-
const archiveUrl = pmtilesUrl(url.startsWith('pmtiles://') ? url : `pmtiles://${url}`);
|
|
736
|
+
export const pmtilesLayer = async (map, url, options) => {
|
|
737
|
+
const archiveUrl = pmtilesUrl(url.startsWith('pmtiles://') ? url : `pmtiles://${url}`) ?? url;
|
|
695
738
|
const archive = pmtiles(archiveUrl);
|
|
696
|
-
const [header, metadata] = await Promise.all([
|
|
739
|
+
const [header, metadata] = await Promise.all([
|
|
740
|
+
archive.header(),
|
|
741
|
+
archive.metadata().catch(() => ({})),
|
|
742
|
+
]);
|
|
697
743
|
const credit = metadata.attribution;
|
|
698
744
|
const attribution = options.attribution ?? (typeof credit === 'string' && credit ? plainText(credit) : undefined);
|
|
699
745
|
const kind = options.kind ?? (header.tileType === 'mvt' ? 'vector' : 'raster');
|
|
@@ -710,7 +756,9 @@ export async function pmtilesLayer(map, url, options) {
|
|
|
710
756
|
});
|
|
711
757
|
}
|
|
712
758
|
const layers = metadata.vector_layers;
|
|
713
|
-
const names = Array.isArray(layers)
|
|
759
|
+
const names = Array.isArray(layers)
|
|
760
|
+
? layers.map((l) => (isRecord(l) ? l.id : undefined)).filter((id) => typeof id === 'string')
|
|
761
|
+
: [];
|
|
714
762
|
const style = options.style ?? basicStyle({ url: `pmtiles://${archiveUrl}` }, names);
|
|
715
763
|
const tiles = map.vectorTiles({ style, ...credits });
|
|
716
764
|
tiles.raster({
|
|
@@ -719,10 +767,10 @@ export async function pmtilesLayer(map, url, options) {
|
|
|
719
767
|
});
|
|
720
768
|
tiles.labels();
|
|
721
769
|
return tiles;
|
|
722
|
-
}
|
|
770
|
+
};
|
|
723
771
|
/** A raster loader reading the tiles of a `pmtiles://` archive URL (images of any size, drawn at `size`); undefined
|
|
724
772
|
* for another URL */
|
|
725
|
-
export
|
|
773
|
+
export const pmtilesRasterLoader = (url, size) => {
|
|
726
774
|
const archiveUrl = pmtilesUrl(url);
|
|
727
775
|
if (!archiveUrl)
|
|
728
776
|
return undefined;
|
|
@@ -733,5 +781,5 @@ export function pmtilesRasterLoader(url, size) {
|
|
|
733
781
|
return null;
|
|
734
782
|
return createImageBitmap(new Blob([bytes]), { resizeWidth: size, resizeHeight: size });
|
|
735
783
|
};
|
|
736
|
-
}
|
|
784
|
+
};
|
|
737
785
|
//# sourceMappingURL=vectortiles.js.map
|