@loaders.gl/mvt 4.0.0-beta.8 → 4.0.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/dist/dist.dev.js +129 -49
- package/dist/index.cjs +115 -44
- package/dist/lib/parse-tilejson.d.ts +20 -4
- package/dist/lib/parse-tilejson.d.ts.map +1 -1
- package/dist/lib/parse-tilejson.js +82 -33
- package/dist/lib/parse-tilejson.js.map +1 -1
- package/dist/mvt-source.d.ts +7 -0
- package/dist/mvt-source.d.ts.map +1 -1
- package/dist/mvt-source.js +42 -16
- package/dist/mvt-source.js.map +1 -1
- package/dist/mvt-worker.js +2 -2
- package/dist/tilejson-loader.d.ts +3 -1
- package/dist/tilejson-loader.d.ts.map +1 -1
- package/dist/tilejson-loader.js +13 -3
- package/dist/tilejson-loader.js.map +1 -1
- package/package.json +6 -6
- package/src/lib/parse-tilejson.ts +137 -42
- package/src/mvt-source.ts +51 -11
- package/src/tilejson-loader.ts +11 -5
|
@@ -1,21 +1,42 @@
|
|
|
1
1
|
// loaders.gl, MIT license
|
|
2
2
|
// Copyright (c) vis.gl contributors
|
|
3
3
|
|
|
4
|
+
export type TileJSONOptions = {
|
|
5
|
+
maxValues?: number | false;
|
|
6
|
+
};
|
|
7
|
+
|
|
4
8
|
/** Parsed and typed TileJSON, merges Tilestats information if present */
|
|
5
9
|
export type TileJSON = {
|
|
6
10
|
name?: string;
|
|
7
11
|
description?: string;
|
|
8
12
|
version?: string;
|
|
13
|
+
|
|
14
|
+
tileFormat?: string;
|
|
15
|
+
tilesetType?: string;
|
|
16
|
+
|
|
17
|
+
/** Generating application. Tippecanoe adds this. */
|
|
18
|
+
generator?: string;
|
|
19
|
+
/** Generating application options. Tippecanoe adds this. */
|
|
20
|
+
generatorOptions?: string;
|
|
21
|
+
|
|
22
|
+
/** Tile indexing scheme */
|
|
9
23
|
scheme?: 'xyz' | 'tms';
|
|
24
|
+
/** Sharded URLs */
|
|
10
25
|
tiles?: string[];
|
|
11
26
|
/** `[[w, s], [e, n]]`, indicates the limits of the bounding box using the axis units and order of the specified CRS. */
|
|
12
27
|
boundingBox?: [min: [w: number, s: number], max: [e: number, n: number]];
|
|
13
|
-
|
|
14
|
-
maxZoom
|
|
15
|
-
minZoom
|
|
28
|
+
/** May be set to the maxZoom of the first layer */
|
|
29
|
+
maxZoom?: number | null;
|
|
30
|
+
/** May be set to the minZoom of the first layer */
|
|
31
|
+
minZoom?: number | null;
|
|
32
|
+
center?: number[] | null;
|
|
16
33
|
htmlAttribution?: string;
|
|
17
34
|
htmlLegend?: string;
|
|
35
|
+
|
|
36
|
+
// Combination of tilestats (if present) and tilejson layer information
|
|
18
37
|
layers?: TileJSONLayer[];
|
|
38
|
+
|
|
39
|
+
/** Any nested JSON metadata */
|
|
19
40
|
metaJson?: any | null;
|
|
20
41
|
};
|
|
21
42
|
|
|
@@ -52,6 +73,8 @@ export type TileJSONField = {
|
|
|
52
73
|
min?: number;
|
|
53
74
|
/** max value (if there are *any* numbers in the values) */
|
|
54
75
|
max?: number;
|
|
76
|
+
/** Number of unique values across the tileset */
|
|
77
|
+
uniqueValueCount?: number;
|
|
55
78
|
/** An array of this attribute's first 100 unique values */
|
|
56
79
|
values?: unknown[];
|
|
57
80
|
};
|
|
@@ -93,50 +116,77 @@ type TilestatsLayerAttribute = {
|
|
|
93
116
|
min?: number;
|
|
94
117
|
/** max value (if there are *any* numbers in the values) */
|
|
95
118
|
max?: number;
|
|
119
|
+
/** Number of unique values */
|
|
120
|
+
count?: number;
|
|
121
|
+
/** First 100 values */
|
|
122
|
+
values?: unknown[];
|
|
96
123
|
};
|
|
97
124
|
|
|
98
125
|
const isObject: (x: unknown) => boolean = (x) => x !== null && typeof x === 'object';
|
|
99
126
|
|
|
100
|
-
export function parseTileJSON(jsonMetadata: any): TileJSON | null {
|
|
127
|
+
export function parseTileJSON(jsonMetadata: any, options: TileJSONOptions): TileJSON | null {
|
|
101
128
|
if (!jsonMetadata || !isObject(jsonMetadata)) {
|
|
102
129
|
return null;
|
|
103
130
|
}
|
|
104
131
|
|
|
105
|
-
const boundingBox = parseBounds(jsonMetadata.bounds);
|
|
106
|
-
const center = parseCenter(jsonMetadata.center);
|
|
107
|
-
const maxZoom = safeParseFloat(jsonMetadata.maxzoom);
|
|
108
|
-
const minZoom = safeParseFloat(jsonMetadata.minzoom);
|
|
109
|
-
|
|
110
132
|
let tileJSON: TileJSON = {
|
|
111
133
|
name: jsonMetadata.name || '',
|
|
112
|
-
description: jsonMetadata.description || ''
|
|
113
|
-
boundingBox,
|
|
114
|
-
center,
|
|
115
|
-
maxZoom,
|
|
116
|
-
minZoom,
|
|
117
|
-
layers: []
|
|
134
|
+
description: jsonMetadata.description || ''
|
|
118
135
|
};
|
|
119
136
|
|
|
120
|
-
//
|
|
137
|
+
// tippecanoe
|
|
138
|
+
|
|
139
|
+
if (typeof jsonMetadata.generator === 'string') {
|
|
140
|
+
tileJSON.generator = jsonMetadata.generator;
|
|
141
|
+
}
|
|
142
|
+
if (typeof jsonMetadata.generator_options === 'string') {
|
|
143
|
+
tileJSON.generatorOptions = jsonMetadata.generator_options;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Tippecanoe emits `antimeridian_adjusted_bounds` instead of `bounds`
|
|
147
|
+
tileJSON.boundingBox =
|
|
148
|
+
parseBounds(jsonMetadata.bounds) || parseBounds(jsonMetadata.antimeridian_adjusted_bounds);
|
|
149
|
+
|
|
150
|
+
// TODO - can be undefined - we could set to center of bounds...
|
|
151
|
+
tileJSON.center = parseCenter(jsonMetadata.center);
|
|
152
|
+
// TODO - can be undefined, we could extract from layers...
|
|
153
|
+
tileJSON.maxZoom = safeParseFloat(jsonMetadata.maxzoom);
|
|
154
|
+
// TODO - can be undefined, we could extract from layers...
|
|
155
|
+
tileJSON.minZoom = safeParseFloat(jsonMetadata.minzoom);
|
|
156
|
+
|
|
157
|
+
// Look for nested metadata embedded in .json field
|
|
158
|
+
// TODO - document what source this applies to, when is this needed?
|
|
121
159
|
if (typeof jsonMetadata?.json === 'string') {
|
|
160
|
+
// try to parse json
|
|
122
161
|
try {
|
|
123
162
|
tileJSON.metaJson = JSON.parse(jsonMetadata.json);
|
|
124
|
-
} catch (
|
|
163
|
+
} catch (error) {
|
|
164
|
+
console.warn('Failed to parse tilejson.json field', error);
|
|
125
165
|
// do nothing
|
|
126
166
|
}
|
|
127
167
|
}
|
|
128
168
|
|
|
129
|
-
|
|
169
|
+
// Look for fields in tilestats
|
|
170
|
+
|
|
171
|
+
const tilestats = jsonMetadata.tilestats || tileJSON.metaJson?.tilestats;
|
|
172
|
+
const tileStatsLayers = parseTilestatsLayers(tilestats, options);
|
|
173
|
+
const tileJSONlayers = parseTileJSONLayers(jsonMetadata.vector_layers); // eslint-disable-line camelcase
|
|
130
174
|
// TODO - merge in description from tilejson
|
|
131
|
-
|
|
132
|
-
layers = parseTileJSONLayers(jsonMetadata.vector_layers); // eslint-disable-line camelcase
|
|
133
|
-
}
|
|
175
|
+
const layers = mergeLayers(tileJSONlayers, tileStatsLayers);
|
|
134
176
|
|
|
135
177
|
tileJSON = {
|
|
136
178
|
...tileJSON,
|
|
137
179
|
layers
|
|
138
180
|
};
|
|
139
181
|
|
|
182
|
+
if (tileJSON.maxZoom === null && layers.length > 0) {
|
|
183
|
+
tileJSON.maxZoom = layers[0].maxZoom || null;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (tileJSON.minZoom === null && layers.length > 0) {
|
|
187
|
+
tileJSON.minZoom = layers[0].minZoom || null;
|
|
188
|
+
}
|
|
189
|
+
|
|
140
190
|
return tileJSON;
|
|
141
191
|
}
|
|
142
192
|
|
|
@@ -145,41 +195,52 @@ function parseTileJSONLayers(layers: any[]): TileJSONLayer[] {
|
|
|
145
195
|
if (!Array.isArray(layers)) {
|
|
146
196
|
return [];
|
|
147
197
|
}
|
|
148
|
-
return layers.map((layer) => (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
198
|
+
return layers.map((layer) => parseTileJSONLayer(layer));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function parseTileJSONLayer(layer: any): TileJSONLayer {
|
|
202
|
+
const fields = Object.entries(layer.fields || []).map(([key, datatype]) => ({
|
|
203
|
+
name: key,
|
|
204
|
+
...attributeTypeToFieldType(String(datatype))
|
|
154
205
|
}));
|
|
206
|
+
const layer2 = {...layer};
|
|
207
|
+
delete layer2.fields;
|
|
208
|
+
return {
|
|
209
|
+
name: layer.id || '',
|
|
210
|
+
...layer2,
|
|
211
|
+
fields
|
|
212
|
+
};
|
|
155
213
|
}
|
|
156
214
|
|
|
157
215
|
/** parse Layers array from tilestats */
|
|
158
|
-
function parseTilestatsLayers(tilestats: any): TileJSONLayer[] {
|
|
216
|
+
function parseTilestatsLayers(tilestats: any, options: TileJSONOptions): TileJSONLayer[] {
|
|
159
217
|
if (isObject(tilestats) && Array.isArray(tilestats.layers)) {
|
|
160
218
|
// we are in luck!
|
|
161
|
-
return tilestats.layers.map((layer) => parseTilestatsForLayer(layer));
|
|
219
|
+
return tilestats.layers.map((layer) => parseTilestatsForLayer(layer, options));
|
|
162
220
|
}
|
|
163
221
|
return [];
|
|
164
222
|
}
|
|
165
223
|
|
|
166
|
-
function parseTilestatsForLayer(layer: TilestatsLayer): TileJSONLayer {
|
|
224
|
+
function parseTilestatsForLayer(layer: TilestatsLayer, options: TileJSONOptions): TileJSONLayer {
|
|
167
225
|
const fields: TileJSONField[] = [];
|
|
168
226
|
const indexedAttributes: {[key: string]: TilestatsLayerAttribute[]} = {};
|
|
169
227
|
|
|
170
228
|
const attributes = layer.attributes || [];
|
|
171
|
-
for (const
|
|
172
|
-
const name =
|
|
229
|
+
for (const attribute of attributes) {
|
|
230
|
+
const name = attribute.attribute;
|
|
173
231
|
if (typeof name === 'string') {
|
|
232
|
+
// TODO - code copied from kepler.gl, need sample tilestats files to test
|
|
174
233
|
if (name.split('|').length > 1) {
|
|
175
234
|
// indexed field
|
|
176
235
|
const fname = name.split('|')[0];
|
|
177
236
|
indexedAttributes[fname] = indexedAttributes[fname] || [];
|
|
178
|
-
indexedAttributes[fname].push(
|
|
237
|
+
indexedAttributes[fname].push(attribute);
|
|
238
|
+
// eslint-disable-next-line no-console
|
|
239
|
+
console.warn('ignoring tilestats indexed field', fname);
|
|
179
240
|
} else if (!fields[name]) {
|
|
180
|
-
fields
|
|
241
|
+
fields.push(attributeToField(attribute, options));
|
|
181
242
|
} else {
|
|
182
|
-
// return (fields[name],
|
|
243
|
+
// return (fields[name], attribute);
|
|
183
244
|
}
|
|
184
245
|
}
|
|
185
246
|
}
|
|
@@ -190,6 +251,21 @@ function parseTilestatsForLayer(layer: TilestatsLayer): TileJSONLayer {
|
|
|
190
251
|
};
|
|
191
252
|
}
|
|
192
253
|
|
|
254
|
+
function mergeLayers(layers: TileJSONLayer[], tilestatsLayers: TileJSONLayer[]): TileJSONLayer[] {
|
|
255
|
+
return layers.map((layer) => {
|
|
256
|
+
const tilestatsLayer = tilestatsLayers.find((tsLayer) => tsLayer.name === layer.name);
|
|
257
|
+
// For aesthetics in JSON dumps, we preserve field order (make sure layers is last)
|
|
258
|
+
const fields = tilestatsLayer?.fields || [];
|
|
259
|
+
const layer2: Partial<TileJSONLayer> = {...layer};
|
|
260
|
+
delete layer2.fields;
|
|
261
|
+
return {
|
|
262
|
+
...layer2,
|
|
263
|
+
...tilestatsLayer,
|
|
264
|
+
fields
|
|
265
|
+
} as TileJSONLayer;
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
193
269
|
/**
|
|
194
270
|
* bounds should be [minLng, minLat, maxLng, maxLat]
|
|
195
271
|
*`[[w, s], [e, n]]`, indicates the limits of the bounding box using the axis units and order of the specified CRS.
|
|
@@ -289,19 +365,38 @@ const attrTypeMap = {
|
|
|
289
365
|
}
|
|
290
366
|
};
|
|
291
367
|
|
|
292
|
-
function attributeToField(
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
// min: 0.24375
|
|
297
|
-
// type: "number"
|
|
368
|
+
function attributeToField(
|
|
369
|
+
attribute: TilestatsLayerAttribute = {},
|
|
370
|
+
options: TileJSONOptions
|
|
371
|
+
): TileJSONField {
|
|
298
372
|
const fieldTypes = attributeTypeToFieldType(attribute.type!);
|
|
299
|
-
|
|
373
|
+
const field: TileJSONField = {
|
|
300
374
|
name: attribute.attribute as string,
|
|
301
375
|
// what happens if attribute type is string...
|
|
302
376
|
// filterProps: getFilterProps(fieldTypes.type, attribute),
|
|
303
377
|
...fieldTypes
|
|
304
378
|
};
|
|
379
|
+
|
|
380
|
+
// attribute: "_season_peaks_color"
|
|
381
|
+
// count: 1000
|
|
382
|
+
// max: 0.95
|
|
383
|
+
// min: 0.24375
|
|
384
|
+
// type: "number"
|
|
385
|
+
|
|
386
|
+
if (typeof attribute.min === 'number') {
|
|
387
|
+
field.min = attribute.min;
|
|
388
|
+
}
|
|
389
|
+
if (typeof attribute.max === 'number') {
|
|
390
|
+
field.max = attribute.max;
|
|
391
|
+
}
|
|
392
|
+
if (typeof attribute.count === 'number') {
|
|
393
|
+
field.uniqueValueCount = attribute.count;
|
|
394
|
+
}
|
|
395
|
+
if (options.maxValues !== false && attribute.values) {
|
|
396
|
+
// Too much data? Add option?
|
|
397
|
+
field.values = attribute.values?.slice(0, options.maxValues);
|
|
398
|
+
}
|
|
399
|
+
return field;
|
|
305
400
|
}
|
|
306
401
|
|
|
307
402
|
function attributeTypeToFieldType(aType: string): {type: string} {
|
package/src/mvt-source.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import type {GetTileParameters, ImageType, DataSourceProps} from '@loaders.gl/loader-utils';
|
|
5
5
|
import type {ImageTileSource, VectorTileSource} from '@loaders.gl/loader-utils';
|
|
6
6
|
import {DataSource, resolvePath} from '@loaders.gl/loader-utils';
|
|
7
|
-
import {ImageLoader} from '@loaders.gl/images';
|
|
7
|
+
import {ImageLoader, getBinaryImageMetadata} from '@loaders.gl/images';
|
|
8
8
|
import {MVTLoader, MVTLoaderOptions, TileJSONLoader, TileJSON} from '@loaders.gl/mvt';
|
|
9
9
|
|
|
10
10
|
import {TileLoadParameters} from '@loaders.gl/loader-utils';
|
|
@@ -21,13 +21,17 @@ export type MVTSourceProps = DataSourceProps & {
|
|
|
21
21
|
export class MVTSource extends DataSource implements ImageTileSource, VectorTileSource {
|
|
22
22
|
props: MVTSourceProps;
|
|
23
23
|
url: string;
|
|
24
|
+
data: string;
|
|
24
25
|
schema: 'tms' | 'xyz' = 'tms';
|
|
25
26
|
metadata: Promise<TileJSON | null>;
|
|
27
|
+
extension = '.png';
|
|
28
|
+
mimeType: string | null = null;
|
|
26
29
|
|
|
27
30
|
constructor(props: MVTSourceProps) {
|
|
28
31
|
super(props);
|
|
29
32
|
this.props = props;
|
|
30
33
|
this.url = resolvePath(props.url);
|
|
34
|
+
this.data = this.url;
|
|
31
35
|
this.getTileData = this.getTileData.bind(this);
|
|
32
36
|
this.metadata = this.getMetadata();
|
|
33
37
|
}
|
|
@@ -35,16 +39,31 @@ export class MVTSource extends DataSource implements ImageTileSource, VectorTile
|
|
|
35
39
|
// @ts-ignore - Metadata type misalignment
|
|
36
40
|
async getMetadata(): Promise<TileJSON | null> {
|
|
37
41
|
const metadataUrl = this.getMetadataUrl();
|
|
38
|
-
|
|
42
|
+
let response: Response;
|
|
43
|
+
try {
|
|
44
|
+
// Annoyingly, fetch throws on CORS errors which is common when requesting an unavailable resource
|
|
45
|
+
response = await this.fetch(metadataUrl);
|
|
46
|
+
} catch (error: unknown) {
|
|
47
|
+
console.error((error as TypeError).message);
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
39
50
|
if (!response.ok) {
|
|
51
|
+
console.error(response.statusText);
|
|
40
52
|
return null;
|
|
41
53
|
}
|
|
42
54
|
const tileJSON = await response.text();
|
|
43
55
|
const metadata = TileJSONLoader.parseTextSync?.(JSON.stringify(tileJSON)) || null;
|
|
44
56
|
// metadata.attributions = [...this.props.attributions, ...(metadata.attributions || [])];
|
|
57
|
+
// if (metadata?.mimeType) {
|
|
58
|
+
// this.mimeType = metadata?.tileMIMEType;
|
|
59
|
+
// }
|
|
45
60
|
return metadata;
|
|
46
61
|
}
|
|
47
62
|
|
|
63
|
+
getTileMIMEType(): string | null {
|
|
64
|
+
return this.mimeType;
|
|
65
|
+
}
|
|
66
|
+
|
|
48
67
|
async getTile(tileParams: GetTileParameters): Promise<ArrayBuffer | null> {
|
|
49
68
|
const {x, y, zoom: z} = tileParams;
|
|
50
69
|
const tileUrl = this.getTileURL(x, y, z);
|
|
@@ -61,27 +80,48 @@ export class MVTSource extends DataSource implements ImageTileSource, VectorTile
|
|
|
61
80
|
|
|
62
81
|
async getTileData(tileParams: TileLoadParameters): Promise<unknown | null> {
|
|
63
82
|
const {x, y, z} = tileParams.index;
|
|
64
|
-
const metadata = await this.metadata;
|
|
65
|
-
//
|
|
66
|
-
|
|
83
|
+
// const metadata = await this.metadata;
|
|
84
|
+
// mimeType = metadata?.tileMIMEType || 'application/vnd.mapbox-vector-tile';
|
|
85
|
+
|
|
86
|
+
const arrayBuffer = await this.getTile({x, y, zoom: z, layers: []});
|
|
87
|
+
if (arrayBuffer === null) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const imageMetadata = getBinaryImageMetadata(arrayBuffer);
|
|
92
|
+
this.mimeType =
|
|
93
|
+
this.mimeType || imageMetadata?.mimeType || 'application/vnd.mapbox-vector-tile';
|
|
94
|
+
switch (this.mimeType) {
|
|
67
95
|
case 'application/vnd.mapbox-vector-tile':
|
|
68
|
-
return await this.
|
|
96
|
+
return await this.parseVectorTile(arrayBuffer, {x, y, zoom: z, layers: []});
|
|
69
97
|
default:
|
|
70
|
-
return await this.
|
|
98
|
+
return await this.parseImageTile(arrayBuffer);
|
|
71
99
|
}
|
|
72
100
|
}
|
|
101
|
+
x;
|
|
73
102
|
|
|
74
103
|
// ImageTileSource interface implementation
|
|
75
104
|
|
|
76
105
|
async getImageTile(tileParams: GetTileParameters): Promise<ImageType | null> {
|
|
77
106
|
const arrayBuffer = await this.getTile(tileParams);
|
|
78
|
-
return arrayBuffer ?
|
|
107
|
+
return arrayBuffer ? this.parseImageTile(arrayBuffer) : null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
protected async parseImageTile(arrayBuffer: ArrayBuffer): Promise<ImageType> {
|
|
111
|
+
return await ImageLoader.parse(arrayBuffer, this.loadOptions);
|
|
79
112
|
}
|
|
80
113
|
|
|
81
114
|
// VectorTileSource interface implementation
|
|
82
115
|
|
|
83
116
|
async getVectorTile(tileParams: GetTileParameters): Promise<unknown | null> {
|
|
84
117
|
const arrayBuffer = await this.getTile(tileParams);
|
|
118
|
+
return arrayBuffer ? this.parseVectorTile(arrayBuffer, tileParams) : null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
protected async parseVectorTile(
|
|
122
|
+
arrayBuffer: ArrayBuffer,
|
|
123
|
+
tileParams: GetTileParameters
|
|
124
|
+
): Promise<unknown | null> {
|
|
85
125
|
const loadOptions: MVTLoaderOptions = {
|
|
86
126
|
shape: 'geojson-table',
|
|
87
127
|
mvt: {
|
|
@@ -92,7 +132,7 @@ export class MVTSource extends DataSource implements ImageTileSource, VectorTile
|
|
|
92
132
|
...this.loadOptions
|
|
93
133
|
};
|
|
94
134
|
|
|
95
|
-
return
|
|
135
|
+
return await MVTLoader.parse(arrayBuffer, loadOptions);
|
|
96
136
|
}
|
|
97
137
|
|
|
98
138
|
getMetadataUrl(): string {
|
|
@@ -102,10 +142,10 @@ export class MVTSource extends DataSource implements ImageTileSource, VectorTile
|
|
|
102
142
|
getTileURL(x: number, y: number, z: number) {
|
|
103
143
|
switch (this.schema) {
|
|
104
144
|
case 'xyz':
|
|
105
|
-
return `${this.url}/${x}/${y}/${z}`;
|
|
145
|
+
return `${this.url}/${x}/${y}/${z}${this.extension}`;
|
|
106
146
|
case 'tms':
|
|
107
147
|
default:
|
|
108
|
-
return `${this.url}/${z}/${x}/${y}`;
|
|
148
|
+
return `${this.url}/${z}/${x}/${y}${this.extension}`;
|
|
109
149
|
}
|
|
110
150
|
}
|
|
111
151
|
}
|
package/src/tilejson-loader.ts
CHANGED
|
@@ -10,7 +10,9 @@ import {parseTileJSON} from './lib/parse-tilejson';
|
|
|
10
10
|
const VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : 'latest';
|
|
11
11
|
|
|
12
12
|
export type TileJSONLoaderOptions = LoaderOptions & {
|
|
13
|
-
tilejson?: {
|
|
13
|
+
tilejson?: {
|
|
14
|
+
maxValues?: number | false;
|
|
15
|
+
};
|
|
14
16
|
};
|
|
15
17
|
|
|
16
18
|
/**
|
|
@@ -26,15 +28,19 @@ export const TileJSONLoader: LoaderWithParser<TileJSON, never, TileJSONLoaderOpt
|
|
|
26
28
|
mimeTypes: ['application/json'],
|
|
27
29
|
text: true,
|
|
28
30
|
options: {
|
|
29
|
-
tilejson: {
|
|
31
|
+
tilejson: {
|
|
32
|
+
maxValues: 10
|
|
33
|
+
}
|
|
30
34
|
},
|
|
31
|
-
parse: async (arrayBuffer, options) => {
|
|
35
|
+
parse: async (arrayBuffer, options?: TileJSONLoaderOptions) => {
|
|
32
36
|
const jsonString = new TextDecoder().decode(arrayBuffer);
|
|
33
37
|
const json = JSON.parse(jsonString);
|
|
34
|
-
|
|
38
|
+
const tilejsonOptions = {...TileJSONLoader.options.tilejson, ...options?.tilejson};
|
|
39
|
+
return parseTileJSON(json, tilejsonOptions) as TileJSON;
|
|
35
40
|
},
|
|
36
41
|
parseTextSync: (text, options) => {
|
|
37
42
|
const json = JSON.parse(text);
|
|
38
|
-
|
|
43
|
+
const tilejsonOptions = {...TileJSONLoader.options.tilejson, ...options?.tilejson};
|
|
44
|
+
return parseTileJSON(json, tilejsonOptions) as TileJSON;
|
|
39
45
|
}
|
|
40
46
|
};
|