@mapwhit/tilerenderer 0.52.0 → 1.0.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/README.md +7 -0
- package/build/min/package.json +1 -1
- package/build/min/src/shaders/_prelude.fragment.glsl.js +2 -2
- package/build/min/src/shaders/_prelude.vertex.glsl.js +2 -2
- package/build/min/src/shaders/background.fragment.glsl.js +2 -2
- package/build/min/src/shaders/background.vertex.glsl.js +1 -1
- package/build/min/src/shaders/background_pattern.fragment.glsl.js +2 -2
- package/build/min/src/shaders/background_pattern.vertex.glsl.js +1 -1
- package/build/min/src/shaders/circle.fragment.glsl.js +2 -2
- package/build/min/src/shaders/circle.vertex.glsl.js +2 -2
- package/build/min/src/shaders/clipping_mask.fragment.glsl.js +1 -1
- package/build/min/src/shaders/clipping_mask.vertex.glsl.js +1 -1
- package/build/min/src/shaders/collision_box.fragment.glsl.js +1 -1
- package/build/min/src/shaders/collision_box.vertex.glsl.js +1 -1
- package/build/min/src/shaders/collision_circle.fragment.glsl.js +1 -1
- package/build/min/src/shaders/collision_circle.vertex.glsl.js +1 -1
- package/build/min/src/shaders/debug.fragment.glsl.js +1 -1
- package/build/min/src/shaders/debug.vertex.glsl.js +1 -1
- package/build/min/src/shaders/fill.fragment.glsl.js +2 -2
- package/build/min/src/shaders/fill.vertex.glsl.js +2 -2
- package/build/min/src/shaders/fill_extrusion.fragment.glsl.js +2 -2
- package/build/min/src/shaders/fill_extrusion.vertex.glsl.js +2 -2
- package/build/min/src/shaders/fill_extrusion_pattern.fragment.glsl.js +2 -2
- package/build/min/src/shaders/fill_extrusion_pattern.vertex.glsl.js +2 -2
- package/build/min/src/shaders/fill_outline.fragment.glsl.js +2 -2
- package/build/min/src/shaders/fill_outline.vertex.glsl.js +2 -2
- package/build/min/src/shaders/fill_outline_pattern.fragment.glsl.js +2 -2
- package/build/min/src/shaders/fill_outline_pattern.vertex.glsl.js +2 -2
- package/build/min/src/shaders/fill_pattern.fragment.glsl.js +2 -2
- package/build/min/src/shaders/fill_pattern.vertex.glsl.js +2 -2
- package/build/min/src/shaders/heatmap.fragment.glsl.js +2 -2
- package/build/min/src/shaders/heatmap.vertex.glsl.js +2 -2
- package/build/min/src/shaders/heatmap_texture.fragment.glsl.js +2 -2
- package/build/min/src/shaders/heatmap_texture.vertex.glsl.js +1 -1
- package/build/min/src/shaders/hillshade.fragment.glsl.js +2 -2
- package/build/min/src/shaders/hillshade.vertex.glsl.js +1 -1
- package/build/min/src/shaders/hillshade_prepare.fragment.glsl.js +2 -2
- package/build/min/src/shaders/hillshade_prepare.vertex.glsl.js +1 -1
- package/build/min/src/shaders/line.fragment.glsl.js +2 -2
- package/build/min/src/shaders/line.vertex.glsl.js +2 -2
- package/build/min/src/shaders/line_gradient.fragment.glsl.js +2 -2
- package/build/min/src/shaders/line_gradient.vertex.glsl.js +2 -2
- package/build/min/src/shaders/line_pattern.fragment.glsl.js +2 -2
- package/build/min/src/shaders/line_pattern.vertex.glsl.js +2 -2
- package/build/min/src/shaders/line_sdf.fragment.glsl.js +2 -2
- package/build/min/src/shaders/line_sdf.vertex.glsl.js +2 -2
- package/build/min/src/shaders/raster.fragment.glsl.js +2 -2
- package/build/min/src/shaders/raster.vertex.glsl.js +1 -1
- package/build/min/src/shaders/symbol_icon.fragment.glsl.js +2 -2
- package/build/min/src/shaders/symbol_icon.vertex.glsl.js +2 -2
- package/build/min/src/shaders/symbol_sdf.fragment.glsl.js +2 -2
- package/build/min/src/shaders/symbol_sdf.vertex.glsl.js +2 -2
- package/package.json +3 -3
- package/src/data/array_types.js +1 -36
- package/src/data/bucket/circle_bucket.js +8 -5
- package/src/data/bucket/fill_bucket.js +8 -5
- package/src/data/bucket/fill_extrusion_bucket.js +8 -5
- package/src/data/bucket/heatmap_bucket.js +0 -4
- package/src/data/bucket/line_bucket.js +9 -6
- package/src/data/bucket/pattern_bucket_features.js +2 -2
- package/src/data/bucket/symbol_bucket.js +99 -129
- package/src/data/bucket.js +26 -21
- package/src/data/dem_data.js +0 -3
- package/src/data/feature_index.js +3 -8
- package/src/data/program_configuration.js +24 -33
- package/src/data/segment.js +0 -4
- package/src/render/draw_background.js +3 -3
- package/src/render/draw_circle.js +4 -4
- package/src/render/draw_fill.js +8 -8
- package/src/render/draw_fill_extrusion.js +8 -8
- package/src/render/draw_heatmap.js +4 -4
- package/src/render/draw_line.js +6 -6
- package/src/render/draw_raster.js +6 -6
- package/src/render/draw_symbol.js +16 -16
- package/src/render/glyph_atlas.js +0 -3
- package/src/render/glyph_manager.js +1 -2
- package/src/render/image_atlas.js +0 -4
- package/src/render/image_manager.js +33 -19
- package/src/render/painter.js +13 -14
- package/src/render/program/circle_program.js +4 -4
- package/src/render/program/fill_extrusion_program.js +1 -1
- package/src/render/program/heatmap_program.js +1 -1
- package/src/render/program/hillshade_program.js +6 -6
- package/src/render/program/line_program.js +3 -3
- package/src/render/program/raster_program.js +6 -6
- package/src/source/geojson_source.js +15 -24
- package/src/source/geojson_worker_source.js +40 -68
- package/src/source/geojson_wrapper.js +9 -1
- package/src/source/image_source.js +6 -16
- package/src/source/query_features.js +4 -5
- package/src/source/raster_dem_tile_source.js +45 -64
- package/src/source/raster_tile_source.js +1 -6
- package/src/source/resources/glyphs.js +2 -2
- package/src/source/resources/index.js +3 -9
- package/src/source/rtl_text_plugin.js +58 -31
- package/src/source/source.js +11 -13
- package/src/source/source_cache.js +135 -151
- package/src/source/source_state.js +101 -12
- package/src/source/tile.js +32 -46
- package/src/source/tile_bounds.js +26 -26
- package/src/source/tile_id.js +2 -5
- package/src/source/vector_tile_source.js +14 -14
- package/src/source/vector_tile_worker_source.js +19 -23
- package/src/source/worker_tile.js +122 -119
- package/src/style/create_style_layer.js +1 -1
- package/src/style/pauseable_placement.js +4 -5
- package/src/style/properties.js +1 -8
- package/src/style/query_utils.js +3 -3
- package/src/style/style.js +286 -216
- package/src/style/style_layer/circle_style_layer.js +13 -11
- package/src/style/style_layer/fill_extrusion_style_layer.js +42 -27
- package/src/style/style_layer/fill_style_layer.js +5 -5
- package/src/style/style_layer/heatmap_style_layer.js +1 -1
- package/src/style/style_layer/hillshade_style_layer.js +1 -1
- package/src/style/style_layer/line_style_layer.js +23 -19
- package/src/style/style_layer/symbol_style_layer.js +13 -13
- package/src/style/style_layer.js +71 -30
- package/src/style/style_layer_index.js +16 -41
- package/src/symbol/anchor.js +0 -4
- package/src/symbol/cross_tile_symbol_index.js +2 -5
- package/src/symbol/opacity_state.js +0 -4
- package/src/symbol/placement.js +3 -3
- package/src/symbol/quads.js +4 -4
- package/src/symbol/symbol_layout.js +7 -7
- package/src/symbol/transform_text.js +1 -1
- package/src/ui/map.js +52 -15
- package/src/util/group_layers.js +41 -0
- package/src/util/image.js +0 -5
- package/src/util/key.js +21 -0
- package/src/util/object.js +8 -53
- package/src/worker.js +1 -4
- package/src/source/resources/images.js +0 -68
- package/src/source/worker.js +0 -110
- package/src/source/worker_source.js +0 -14
- package/src/style-spec/deref.js +0 -51
- package/src/style-spec/group_by_layout.js +0 -46
- package/src/util/actor.js +0 -108
- package/src/util/dispatcher.js +0 -65
- package/src/util/global_worker_pool.js +0 -15
- package/src/util/transfer_registry.js +0 -168
- package/src/util/web_worker_transfer.js +0 -43
- package/src/util/worker_pool.js +0 -41
package/src/symbol/quads.js
CHANGED
|
@@ -22,7 +22,7 @@ const { GLYPH_PBF_BORDER } = require('../style/parse_glyph_pbf');
|
|
|
22
22
|
*/
|
|
23
23
|
function getIconQuads(anchor, shapedIcon, layer, alongLine, shapedText, feature) {
|
|
24
24
|
const image = shapedIcon.image;
|
|
25
|
-
const layout = layer.
|
|
25
|
+
const layout = layer._layout;
|
|
26
26
|
|
|
27
27
|
// If you have a 10px icon that isn't perfectly aligned to the pixel grid it will cover 11 actual
|
|
28
28
|
// pixels. The quad needs to be padded to account for this, otherwise they'll look slightly clipped
|
|
@@ -71,7 +71,7 @@ function getIconQuads(anchor, shapedIcon, layer, alongLine, shapedText, feature)
|
|
|
71
71
|
bl = new Point(left, bottom);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
const angle = (layer.
|
|
74
|
+
const angle = (layer._layout.get('icon-rotate').evaluate(feature, {}) * Math.PI) / 180;
|
|
75
75
|
|
|
76
76
|
if (angle) {
|
|
77
77
|
const sin = Math.sin(angle);
|
|
@@ -94,8 +94,8 @@ function getIconQuads(anchor, shapedIcon, layer, alongLine, shapedText, feature)
|
|
|
94
94
|
*/
|
|
95
95
|
function getGlyphQuads(anchor, shaping, layer, alongLine, feature, positions) {
|
|
96
96
|
const oneEm = 24;
|
|
97
|
-
const textRotate = (layer.
|
|
98
|
-
const textOffset = layer.
|
|
97
|
+
const textRotate = (layer._layout.get('text-rotate').evaluate(feature, {}) * Math.PI) / 180;
|
|
98
|
+
const textOffset = layer._layout
|
|
99
99
|
.get('text-offset')
|
|
100
100
|
.evaluate(feature, {})
|
|
101
101
|
.map(t => t * oneEm);
|
|
@@ -26,7 +26,7 @@ const murmur3 = require('murmurhash-js');
|
|
|
26
26
|
// 5. For composite `*-size` expressions: two zoom levels of curve stops that "cover" the zoom level of the
|
|
27
27
|
// bucket. These go into a vertex buffer and are used by the shader to interpolate the size at render time.
|
|
28
28
|
//
|
|
29
|
-
// (1) and (2) are stored in `bucket.layers[0].
|
|
29
|
+
// (1) and (2) are stored in `bucket.layers[0]._layout`. The remainder are below.
|
|
30
30
|
//
|
|
31
31
|
|
|
32
32
|
function performSymbolLayout(bucket, glyphMap, glyphPositions, imageMap, imagePositions, showCollisionBoxes) {
|
|
@@ -37,7 +37,7 @@ function performSymbolLayout(bucket, glyphMap, glyphPositions, imageMap, imagePo
|
|
|
37
37
|
bucket.compareText = {};
|
|
38
38
|
bucket.iconsNeedLinear = false;
|
|
39
39
|
|
|
40
|
-
const layout = bucket.layers[0].
|
|
40
|
+
const layout = bucket.layers[0]._layout;
|
|
41
41
|
const unevaluatedLayoutValues = bucket.layers[0]._unevaluatedLayout._values;
|
|
42
42
|
|
|
43
43
|
const sizes = {};
|
|
@@ -172,7 +172,7 @@ function addFeature(bucket, feature, shapedTextOrientations, shapedIcon, glyphPo
|
|
|
172
172
|
textMaxSize = layoutTextSize;
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
const layout = bucket.layers[0].
|
|
175
|
+
const layout = bucket.layers[0]._layout;
|
|
176
176
|
const textOffset = layout.get('text-offset').evaluate(feature, {});
|
|
177
177
|
const iconOffset = layout.get('icon-offset').evaluate(feature, {});
|
|
178
178
|
|
|
@@ -301,7 +301,7 @@ function addTextVertices(
|
|
|
301
301
|
let textSizeData = null;
|
|
302
302
|
|
|
303
303
|
if (sizeData.functionType === 'source') {
|
|
304
|
-
textSizeData = [10 * layer.
|
|
304
|
+
textSizeData = [10 * layer._layout.get('text-size').evaluate(feature, {})];
|
|
305
305
|
} else if (sizeData.functionType === 'composite') {
|
|
306
306
|
textSizeData = [
|
|
307
307
|
10 * sizes.compositeTextSizes[0].evaluate(feature, {}),
|
|
@@ -370,7 +370,7 @@ function addSymbol(
|
|
|
370
370
|
if (shapedTextOrientations.horizontal) {
|
|
371
371
|
// As a collision approximation, we can use either the vertical or the horizontal version of the feature
|
|
372
372
|
// We're counting on the two versions having similar dimensions
|
|
373
|
-
const textRotate = layer.
|
|
373
|
+
const textRotate = layer._layout.get('text-rotate').evaluate(feature, {});
|
|
374
374
|
textCollisionFeature = new CollisionFeature(
|
|
375
375
|
collisionBoxArray,
|
|
376
376
|
line,
|
|
@@ -430,7 +430,7 @@ function addSymbol(
|
|
|
430
430
|
shapedTextOrientations.horizontal,
|
|
431
431
|
feature
|
|
432
432
|
);
|
|
433
|
-
const iconRotate = layer.
|
|
433
|
+
const iconRotate = layer._layout.get('icon-rotate').evaluate(feature, {});
|
|
434
434
|
iconCollisionFeature = new CollisionFeature(
|
|
435
435
|
collisionBoxArray,
|
|
436
436
|
line,
|
|
@@ -452,7 +452,7 @@ function addSymbol(
|
|
|
452
452
|
let iconSizeData = null;
|
|
453
453
|
|
|
454
454
|
if (sizeData.functionType === 'source') {
|
|
455
|
-
iconSizeData = [10 * layer.
|
|
455
|
+
iconSizeData = [10 * layer._layout.get('icon-size').evaluate(feature, {})];
|
|
456
456
|
} else if (sizeData.functionType === 'composite') {
|
|
457
457
|
iconSizeData = [
|
|
458
458
|
10 * sizes.compositeIconSizes[0].evaluate(feature, {}),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { plugin: rtlTextPlugin } = require('../source/rtl_text_plugin');
|
|
2
2
|
|
|
3
3
|
function transformText(text, layer, feature) {
|
|
4
|
-
const transform = layer.
|
|
4
|
+
const transform = layer._layout.get('text-transform').evaluate(feature, {});
|
|
5
5
|
if (transform === 'uppercase') {
|
|
6
6
|
text = text.toLocaleUpperCase();
|
|
7
7
|
} else if (transform === 'lowercase') {
|
package/src/ui/map.js
CHANGED
|
@@ -41,10 +41,6 @@ const defaultOptions = {
|
|
|
41
41
|
|
|
42
42
|
renderWorldCopies: true,
|
|
43
43
|
|
|
44
|
-
refreshExpiredTiles: true,
|
|
45
|
-
|
|
46
|
-
maxTileCacheSize: null,
|
|
47
|
-
|
|
48
44
|
transformRequest: null,
|
|
49
45
|
fadeDuration: 300,
|
|
50
46
|
crossSourceCollisions: true
|
|
@@ -98,7 +94,6 @@ const defaultOptions = {
|
|
|
98
94
|
* @param {number} [options.bearing=0] The initial bearing (rotation) of the map, measured in degrees counter-clockwise from north. If `bearing` is not specified in the constructor options, Mapbox GL JS will look for it in the map's style object. If it is not specified in the style, either, it will default to `0`.
|
|
99
95
|
* @param {number} [options.pitch=0] The initial pitch (tilt) of the map, measured in degrees away from the plane of the screen (0-60). If `pitch` is not specified in the constructor options, Mapbox GL JS will look for it in the map's style object. If it is not specified in the style, either, it will default to `0`.
|
|
100
96
|
* @param {boolean} [options.renderWorldCopies=true] If `true`, multiple copies of the world will be rendered, when zoomed out.
|
|
101
|
-
* @param {number} [options.maxTileCacheSize=null] The maximum number of tiles stored in the tile cache for a given source. If omitted, the cache will be dynamically sized based on the current viewport.
|
|
102
97
|
* @param {number} [options.fadeDuration=300] Controls the duration of the fade-in/fade-out animation for label collisions, in milliseconds. This setting affects all symbol layers. This setting does not affect the duration of runtime styling transitions or raster tile cross-fading.
|
|
103
98
|
* @param {boolean} [options.crossSourceCollisions=true] If `true`, symbols from multiple sources can collide with each other during collision detection. If `false`, collision detection is run separately for the symbols in each source.
|
|
104
99
|
* @example
|
|
@@ -125,7 +120,6 @@ class Map extends Camera {
|
|
|
125
120
|
this.loadImage = loadImage;
|
|
126
121
|
|
|
127
122
|
this._interactive = options.interactive;
|
|
128
|
-
this._maxTileCacheSize = options.maxTileCacheSize;
|
|
129
123
|
this._failIfMajorPerformanceCaveat = options.failIfMajorPerformanceCaveat;
|
|
130
124
|
this._preserveDrawingBuffer = options.preserveDrawingBuffer;
|
|
131
125
|
this._trackResize = options.trackResize;
|
|
@@ -205,14 +199,13 @@ class Map extends Camera {
|
|
|
205
199
|
* Sets a global state property that can be retrieved with the [`global-state` expression](https://maplibre.org/maplibre-style-spec/expressions/#global-state).
|
|
206
200
|
* If the value is null, it resets the property to its default value defined in the [`state` style property](https://maplibre.org/maplibre-style-spec/root/#state).
|
|
207
201
|
*
|
|
208
|
-
* Note that changing `global-state` values defined in layout properties is not supported, and will be ignored.
|
|
209
|
-
*
|
|
210
202
|
* @param propertyName - The name of the state property to set.
|
|
211
203
|
* @param value - The value of the state property to set.
|
|
212
204
|
*/
|
|
213
205
|
setGlobalStateProperty(propertyName, value) {
|
|
214
|
-
this.style.setGlobalStateProperty(propertyName, value)
|
|
215
|
-
|
|
206
|
+
if (!this.style.setGlobalStateProperty(propertyName, value)) {
|
|
207
|
+
return this._update(true);
|
|
208
|
+
}
|
|
216
209
|
}
|
|
217
210
|
|
|
218
211
|
/**
|
|
@@ -688,7 +681,7 @@ class Map extends Camera {
|
|
|
688
681
|
*/
|
|
689
682
|
getStyle() {
|
|
690
683
|
if (this.style) {
|
|
691
|
-
return this.style.serialize();
|
|
684
|
+
return this.style.serialize?.() ?? this.style;
|
|
692
685
|
}
|
|
693
686
|
}
|
|
694
687
|
|
|
@@ -728,7 +721,7 @@ class Map extends Camera {
|
|
|
728
721
|
* @returns {boolean} A Boolean indicating whether the source is loaded.
|
|
729
722
|
*/
|
|
730
723
|
isSourceLoaded(id) {
|
|
731
|
-
const source = this.style?.
|
|
724
|
+
const source = this.style?._sources[id];
|
|
732
725
|
if (source === undefined) {
|
|
733
726
|
this.fire(new ErrorEvent(new Error(`There is no source with ID '${id}'`)));
|
|
734
727
|
return;
|
|
@@ -744,12 +737,11 @@ class Map extends Camera {
|
|
|
744
737
|
*/
|
|
745
738
|
|
|
746
739
|
areTilesLoaded() {
|
|
747
|
-
const sources = this.style?.
|
|
740
|
+
const sources = this.style?._sources;
|
|
748
741
|
for (const id in sources) {
|
|
749
742
|
const source = sources[id];
|
|
750
743
|
const tiles = source._tiles;
|
|
751
|
-
for (const
|
|
752
|
-
const tile = tiles[t];
|
|
744
|
+
for (const tile of tiles.values()) {
|
|
753
745
|
if (!(tile.state === 'loaded' || tile.state === 'errored')) return false;
|
|
754
746
|
}
|
|
755
747
|
}
|
|
@@ -799,6 +791,16 @@ class Map extends Camera {
|
|
|
799
791
|
*/
|
|
800
792
|
addImage(id, image, { pixelRatio = 1, sdf = false } = {}) {
|
|
801
793
|
if (image instanceof HTMLImageElement) {
|
|
794
|
+
if (!image.complete) {
|
|
795
|
+
const promise = new Promise(resolve => {
|
|
796
|
+
image.decode().then(() => {
|
|
797
|
+
const { width, height, data } = browser.getImageData(image);
|
|
798
|
+
resolve({ data: new RGBAImage({ width, height }, data), pixelRatio, sdf });
|
|
799
|
+
});
|
|
800
|
+
});
|
|
801
|
+
this.style.addImage(id, { promise });
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
802
804
|
const { width, height, data } = browser.getImageData(image);
|
|
803
805
|
this.style.addImage(id, { data: new RGBAImage({ width, height }, data), pixelRatio, sdf });
|
|
804
806
|
} else if (image.width === undefined || image.height === undefined) {
|
|
@@ -820,6 +822,23 @@ class Map extends Camera {
|
|
|
820
822
|
}
|
|
821
823
|
}
|
|
822
824
|
|
|
825
|
+
/**
|
|
826
|
+
* Returns an image, specified by ID, currently available in the map.
|
|
827
|
+
* This includes both images from the style's original sprite
|
|
828
|
+
* and any images that have been added at runtime using {@link Map.addImage}.
|
|
829
|
+
*
|
|
830
|
+
* @param id - The ID of the image.
|
|
831
|
+
* @returns An image in the map with the specified ID.
|
|
832
|
+
*
|
|
833
|
+
* @example
|
|
834
|
+
* ```js
|
|
835
|
+
* let coffeeShopIcon = map.getImage("coffee_cup");
|
|
836
|
+
* ```
|
|
837
|
+
*/
|
|
838
|
+
getImage(id) {
|
|
839
|
+
return this.style.getImage(id);
|
|
840
|
+
}
|
|
841
|
+
|
|
823
842
|
/**
|
|
824
843
|
* Define wether the image has been added or not
|
|
825
844
|
*
|
|
@@ -1055,6 +1074,24 @@ class Map extends Camera {
|
|
|
1055
1074
|
this._update();
|
|
1056
1075
|
}
|
|
1057
1076
|
|
|
1077
|
+
/**
|
|
1078
|
+
* Removes feature state, setting it back to the default behavior. If only
|
|
1079
|
+
* source is specified, removes all states of that source. If
|
|
1080
|
+
* target.id is also specified, removes all keys for that feature's state.
|
|
1081
|
+
* If key is also specified, removes that key from that feature's state.
|
|
1082
|
+
*
|
|
1083
|
+
* @param {Object} target Identifier of where to set state: can be a source, a feature, or a specific key of feature.
|
|
1084
|
+
* Feature objects returned from {@link Map#queryRenderedFeatures} or event handlers can be used as feature identifiers.
|
|
1085
|
+
* @param {string | number} target.id (optional) Unique id of the feature. Optional if key is not specified.
|
|
1086
|
+
* @param {string} target.source The Id of the vector source or GeoJSON source for the feature.
|
|
1087
|
+
* @param {string} [target.sourceLayer] (optional) *For vector tile sources, the sourceLayer is
|
|
1088
|
+
* required.*
|
|
1089
|
+
* @param {string} key (optional) The key in the feature state to reset.
|
|
1090
|
+
*/
|
|
1091
|
+
removeFeatureState(target, key) {
|
|
1092
|
+
this.style.removeFeatureState(target, key);
|
|
1093
|
+
return this._update();
|
|
1094
|
+
}
|
|
1058
1095
|
/**
|
|
1059
1096
|
* Gets the state of a feature.
|
|
1060
1097
|
*
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module.exports = groupBySource;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Given an collection of layers, divide them by property 'source', then by 'source-layer',
|
|
5
|
+
* and then by layout-affecting properties: 'type', , 'minzoom', 'maxzoom', 'filter', and 'layout'.
|
|
6
|
+
*
|
|
7
|
+
* The input is not modified. The output layers are references to the
|
|
8
|
+
* input layers.
|
|
9
|
+
*
|
|
10
|
+
* @param layers iterable collection of layers
|
|
11
|
+
* @returns Map source to {Map source-layer to {Map layout key to Array of layers}}
|
|
12
|
+
*/
|
|
13
|
+
function groupBySource(layers) {
|
|
14
|
+
const groups = new Map();
|
|
15
|
+
|
|
16
|
+
// Iterate through each layer and group them by source, source-layer, and layout properties
|
|
17
|
+
for (const layer of layers) {
|
|
18
|
+
if (layer.visibility === 'none') {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const { source = '', sourceLayer = '_geojsonTileLayer' } = layer;
|
|
23
|
+
let sourceGroup = groups.get(source);
|
|
24
|
+
if (!sourceGroup) {
|
|
25
|
+
sourceGroup = new Map();
|
|
26
|
+
groups.set(source, sourceGroup);
|
|
27
|
+
}
|
|
28
|
+
let sourceLayerGroup = sourceGroup.get(sourceLayer);
|
|
29
|
+
if (!sourceLayerGroup) {
|
|
30
|
+
sourceLayerGroup = new Map();
|
|
31
|
+
sourceGroup.set(sourceLayer, sourceLayerGroup);
|
|
32
|
+
}
|
|
33
|
+
let layoutGroup = sourceLayerGroup.get(layer.key);
|
|
34
|
+
if (!layoutGroup) {
|
|
35
|
+
layoutGroup = [];
|
|
36
|
+
sourceLayerGroup.set(layer.key, layoutGroup);
|
|
37
|
+
}
|
|
38
|
+
layoutGroup.push(layer);
|
|
39
|
+
}
|
|
40
|
+
return groups;
|
|
41
|
+
}
|
package/src/util/image.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
const assert = require('assert');
|
|
2
2
|
|
|
3
|
-
const { register } = require('./transfer_registry');
|
|
4
|
-
|
|
5
3
|
function createImage(image, { width, height }, channels, data) {
|
|
6
4
|
if (!data) {
|
|
7
5
|
data = new Uint8Array(width * height * channels);
|
|
@@ -115,9 +113,6 @@ class RGBAImage {
|
|
|
115
113
|
}
|
|
116
114
|
}
|
|
117
115
|
|
|
118
|
-
register('AlphaImage', AlphaImage);
|
|
119
|
-
register('RGBAImage', RGBAImage);
|
|
120
|
-
|
|
121
116
|
module.exports = {
|
|
122
117
|
AlphaImage,
|
|
123
118
|
RGBAImage
|
package/src/util/key.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module.exports = createKey;
|
|
2
|
+
|
|
3
|
+
function stringify(obj) {
|
|
4
|
+
if (obj == null) return 'null';
|
|
5
|
+
const type = typeof obj;
|
|
6
|
+
if (type === 'number' || type === 'boolean' || type === 'string') return obj;
|
|
7
|
+
|
|
8
|
+
if (Array.isArray(obj)) {
|
|
9
|
+
return '[' + obj.map(val => stringify(val)).join(',') + ']';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const keys = Object.keys(obj).sort();
|
|
13
|
+
return '{' + keys.map(key => `${key}:${stringify(obj[key])}`).join(',') + '}';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Create a unique key for an based on its properties.
|
|
18
|
+
*/
|
|
19
|
+
function createKey(properties, object) {
|
|
20
|
+
return properties.map(k => stringify(object[k])).join('/');
|
|
21
|
+
}
|
package/src/util/object.js
CHANGED
|
@@ -1,34 +1,3 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Polyfill for Object.values. Not fully spec compliant, but we don't
|
|
3
|
-
* need it to be.
|
|
4
|
-
*
|
|
5
|
-
* @private
|
|
6
|
-
*/
|
|
7
|
-
function values(obj) {
|
|
8
|
-
const result = [];
|
|
9
|
-
for (const k in obj) {
|
|
10
|
-
result.push(obj[k]);
|
|
11
|
-
}
|
|
12
|
-
return result;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/*
|
|
16
|
-
* Compute the difference between the keys in one object and the keys
|
|
17
|
-
* in another object.
|
|
18
|
-
*
|
|
19
|
-
* @returns keys difference
|
|
20
|
-
* @private
|
|
21
|
-
*/
|
|
22
|
-
function keysDifference(obj, other) {
|
|
23
|
-
const difference = [];
|
|
24
|
-
for (const i in obj) {
|
|
25
|
-
if (!(i in other)) {
|
|
26
|
-
difference.push(i);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return difference;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
1
|
/**
|
|
33
2
|
* Given an object and a number of properties as strings, return version
|
|
34
3
|
* of that object with only those properties.
|
|
@@ -44,14 +13,8 @@ function keysDifference(obj, other) {
|
|
|
44
13
|
* @private
|
|
45
14
|
*/
|
|
46
15
|
function pick(src, properties) {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
const k = properties[i];
|
|
50
|
-
if (k in src) {
|
|
51
|
-
result[k] = src[k];
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return result;
|
|
16
|
+
const entries = properties.filter(p => p in src).map(p => [p, src[p]]);
|
|
17
|
+
return Object.fromEntries(entries);
|
|
55
18
|
}
|
|
56
19
|
|
|
57
20
|
/**
|
|
@@ -91,11 +54,9 @@ function bindAll(fns, context) {
|
|
|
91
54
|
* @private
|
|
92
55
|
*/
|
|
93
56
|
function mapObject(input, iterator, context) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
return output;
|
|
57
|
+
context ??= this;
|
|
58
|
+
const entries = Object.entries(input).map(([k, v]) => [k, iterator.call(context, v, k, input)]);
|
|
59
|
+
return Object.fromEntries(entries);
|
|
99
60
|
}
|
|
100
61
|
|
|
101
62
|
/**
|
|
@@ -104,13 +65,9 @@ function mapObject(input, iterator, context) {
|
|
|
104
65
|
* @private
|
|
105
66
|
*/
|
|
106
67
|
function filterObject(input, iterator, context) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
output[key] = input[key];
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return output;
|
|
68
|
+
context ??= this;
|
|
69
|
+
const entries = Object.entries(input).filter(([k, v]) => iterator.call(context, v, k, input));
|
|
70
|
+
return Object.fromEntries(entries);
|
|
114
71
|
}
|
|
115
72
|
|
|
116
73
|
/**
|
|
@@ -166,8 +123,6 @@ function arraysIntersect(a, b) {
|
|
|
166
123
|
}
|
|
167
124
|
|
|
168
125
|
module.exports = {
|
|
169
|
-
values,
|
|
170
|
-
keysDifference,
|
|
171
126
|
pick,
|
|
172
127
|
bindAll,
|
|
173
128
|
mapObject,
|
package/src/worker.js
CHANGED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
module.exports = images;
|
|
2
|
-
|
|
3
|
-
function images({ actor, mapId }) {
|
|
4
|
-
const cache = new Map(); // id -> image
|
|
5
|
-
const inProgress = new Map(); // id -> promise
|
|
6
|
-
|
|
7
|
-
return {
|
|
8
|
-
getImages
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
async function getImages({ icons }) {
|
|
12
|
-
const missing = new Set();
|
|
13
|
-
const result = {};
|
|
14
|
-
for (const id of icons) {
|
|
15
|
-
if (cache.has(id)) {
|
|
16
|
-
const image = cache.get(id);
|
|
17
|
-
if (image) {
|
|
18
|
-
result[id] = image;
|
|
19
|
-
}
|
|
20
|
-
} else {
|
|
21
|
-
missing.add(id);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
if (missing.size === 0) {
|
|
25
|
-
// All images are already in the cache
|
|
26
|
-
return result;
|
|
27
|
-
}
|
|
28
|
-
const active = new Set();
|
|
29
|
-
const needed = [...missing];
|
|
30
|
-
// Check if any of the missing images are already being fetched
|
|
31
|
-
for (const id of missing) {
|
|
32
|
-
if (inProgress.has(id)) {
|
|
33
|
-
active.add(inProgress.get(id));
|
|
34
|
-
missing.delete(id);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
if (missing.size > 0) {
|
|
38
|
-
// Fetch the remaining images
|
|
39
|
-
await fetchMissing([...missing]);
|
|
40
|
-
}
|
|
41
|
-
if (active.size > 0) {
|
|
42
|
-
await Promise.all(active);
|
|
43
|
-
}
|
|
44
|
-
for (const id of needed) {
|
|
45
|
-
const image = cache.get(id);
|
|
46
|
-
if (image) {
|
|
47
|
-
result[id] = image;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return result;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async function fetchMissing(icons) {
|
|
54
|
-
const promise = actor.send('getImages', { icons }, mapId);
|
|
55
|
-
for (const id of icons) {
|
|
56
|
-
inProgress.set(id, promise);
|
|
57
|
-
}
|
|
58
|
-
const result = await promise;
|
|
59
|
-
// Add the fetched images to the cache
|
|
60
|
-
for (const id of icons) {
|
|
61
|
-
cache.set(id, result[id]);
|
|
62
|
-
}
|
|
63
|
-
// Remove the fetched images from the inProgress set
|
|
64
|
-
for (const id of icons) {
|
|
65
|
-
inProgress.delete(id);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
package/src/source/worker.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
require('../util/polyfill');
|
|
2
|
-
|
|
3
|
-
const Actor = require('../util/actor');
|
|
4
|
-
|
|
5
|
-
const StyleLayerIndex = require('../style/style_layer_index');
|
|
6
|
-
const VectorTileWorkerSource = require('./vector_tile_worker_source');
|
|
7
|
-
const GeoJSONWorkerSource = require('./geojson_worker_source');
|
|
8
|
-
const assert = require('assert');
|
|
9
|
-
const { plugin: globalRTLTextPlugin } = require('./rtl_text_plugin');
|
|
10
|
-
const DEMData = require('../data/dem_data');
|
|
11
|
-
const { resources } = require('./resources');
|
|
12
|
-
|
|
13
|
-
class Worker {
|
|
14
|
-
#resources = {};
|
|
15
|
-
|
|
16
|
-
constructor(self) {
|
|
17
|
-
this.self = self;
|
|
18
|
-
this.actor = new Actor(self, this);
|
|
19
|
-
|
|
20
|
-
this.actors = {};
|
|
21
|
-
this.layerIndexes = {};
|
|
22
|
-
|
|
23
|
-
this.workerSourceTypes = {
|
|
24
|
-
vector: VectorTileWorkerSource,
|
|
25
|
-
geojson: GeoJSONWorkerSource
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// [mapId][sourceType][sourceName] => worker source instance
|
|
29
|
-
this.workerSources = {};
|
|
30
|
-
|
|
31
|
-
this.self.registerWorkerSource = (name, WorkerSource) => {
|
|
32
|
-
if (this.workerSourceTypes[name]) {
|
|
33
|
-
throw new Error(`Worker source with name "${name}" already registered.`);
|
|
34
|
-
}
|
|
35
|
-
this.workerSourceTypes[name] = WorkerSource;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
this.self.registerRTLTextPlugin = rtlTextPlugin => {
|
|
39
|
-
if (globalRTLTextPlugin.isLoaded()) {
|
|
40
|
-
throw new Error('RTL text plugin already registered.');
|
|
41
|
-
}
|
|
42
|
-
globalRTLTextPlugin['applyArabicShaping'] = rtlTextPlugin.applyArabicShaping;
|
|
43
|
-
globalRTLTextPlugin['processBidirectionalText'] = rtlTextPlugin.processBidirectionalText;
|
|
44
|
-
globalRTLTextPlugin['processStyledBidirectionalText'] = rtlTextPlugin.processStyledBidirectionalText;
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
setLayers(mapId, layers) {
|
|
49
|
-
this.getLayerIndex(mapId).replace(layers);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
updateLayers(mapId, params) {
|
|
53
|
-
this.getLayerIndex(mapId).update(params.layers, params.removedIds);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
loadTile(mapId, params) {
|
|
57
|
-
assert(params.type);
|
|
58
|
-
return this.getWorkerSource(mapId, params.type, params.source).loadTile(params);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
loadDEMTile(mapId, params) {
|
|
62
|
-
const { uid, rawImageData, encoding } = params;
|
|
63
|
-
return new DEMData(uid, rawImageData, encoding);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
removeSource(mapId, params) {
|
|
67
|
-
const { type, source } = params;
|
|
68
|
-
assert(type);
|
|
69
|
-
assert(source);
|
|
70
|
-
|
|
71
|
-
const worker = this.workerSources?.[mapId]?.[type]?.[source];
|
|
72
|
-
if (worker) {
|
|
73
|
-
delete this.workerSources[mapId][type][source];
|
|
74
|
-
worker.removeSource?.(params);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
loadRTLTextPlugin(map, pluginURL) {
|
|
79
|
-
if (!globalRTLTextPlugin.isLoaded()) {
|
|
80
|
-
this.self.importScripts(pluginURL);
|
|
81
|
-
if (!globalRTLTextPlugin.isLoaded()) {
|
|
82
|
-
throw new Error(`RTL Text Plugin failed to import scripts from ${pluginURL}`);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
getLayerIndex(mapId) {
|
|
88
|
-
return (this.layerIndexes[mapId] ??= new StyleLayerIndex());
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
getResources(mapId) {
|
|
92
|
-
return (this.#resources[mapId] ??= resources(this.actor, mapId));
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
getWorkerSource(mapId, type, source) {
|
|
96
|
-
this.workerSources[mapId] ??= {};
|
|
97
|
-
this.workerSources[mapId][type] ??= {};
|
|
98
|
-
|
|
99
|
-
return (this.workerSources[mapId][type][source] ??= this.createWorkerSource(type, mapId));
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
createWorkerSource(type, mapId) {
|
|
103
|
-
const WorkerSource = this.workerSourceTypes[type];
|
|
104
|
-
return new WorkerSource(this.getResources(mapId), this.getLayerIndex(mapId));
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
module.exports = function createWorker(self) {
|
|
109
|
-
return new Worker(self);
|
|
110
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* May be implemented by custom source types to provide code that can be run on
|
|
3
|
-
* the WebWorkers. In addition to providing a custom
|
|
4
|
-
* {@link WorkerSource#loadTile}, any other methods attached to a `WorkerSource`
|
|
5
|
-
* implementation may also be targeted by the {@link Source} via
|
|
6
|
-
* `dispatcher.send('source-type.methodname', params, callback)`.
|
|
7
|
-
*
|
|
8
|
-
* @see {@link Map#addSourceType}
|
|
9
|
-
* @private
|
|
10
|
-
*
|
|
11
|
-
* @class WorkerSource
|
|
12
|
-
* @param actor
|
|
13
|
-
* @param layerIndex
|
|
14
|
-
*/
|
package/src/style-spec/deref.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
const refProperties = require('./util/ref_properties');
|
|
2
|
-
|
|
3
|
-
function deref(layer, parent) {
|
|
4
|
-
const result = {};
|
|
5
|
-
|
|
6
|
-
for (const k in layer) {
|
|
7
|
-
if (k !== 'ref') {
|
|
8
|
-
result[k] = layer[k];
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
refProperties.forEach(k => {
|
|
13
|
-
if (k in parent) {
|
|
14
|
-
result[k] = parent[k];
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
return result;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
module.exports = derefLayers;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Given an array of layers, some of which may contain `ref` properties
|
|
25
|
-
* whose value is the `id` of another property, return a new array where
|
|
26
|
-
* such layers have been augmented with the 'type', 'source', etc. properties
|
|
27
|
-
* from the parent layer, and the `ref` property has been removed.
|
|
28
|
-
*
|
|
29
|
-
* The input is not modified. The output may contain references to portions
|
|
30
|
-
* of the input.
|
|
31
|
-
*
|
|
32
|
-
* @private
|
|
33
|
-
* @param {Array<Layer>} layers
|
|
34
|
-
* @returns {Array<Layer>}
|
|
35
|
-
*/
|
|
36
|
-
function derefLayers(layers) {
|
|
37
|
-
layers = layers.slice();
|
|
38
|
-
|
|
39
|
-
const map = Object.create(null);
|
|
40
|
-
for (let i = 0; i < layers.length; i++) {
|
|
41
|
-
map[layers[i].id] = layers[i];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
for (let i = 0; i < layers.length; i++) {
|
|
45
|
-
if ('ref' in layers[i]) {
|
|
46
|
-
layers[i] = deref(layers[i], map[layers[i].ref]);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return layers;
|
|
51
|
-
}
|