maplibre-gl 6.3.0 → 6.4.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/maplibre-gl-dev.mjs +592 -209
- package/dist/maplibre-gl-dev.mjs.map +1 -1
- package/dist/maplibre-gl-shared-dev.mjs +258 -235
- package/dist/maplibre-gl-shared-dev.mjs.map +1 -1
- package/dist/maplibre-gl-shared.mjs +2 -2
- package/dist/maplibre-gl-shared.mjs.map +1 -1
- package/dist/maplibre-gl-worker-dev.mjs +2 -2
- package/dist/maplibre-gl-worker.mjs +2 -2
- package/dist/maplibre-gl-worker.mjs.map +1 -1
- package/dist/maplibre-gl.d.ts +258 -97
- package/dist/maplibre-gl.mjs +18 -18
- package/dist/maplibre-gl.mjs.map +1 -1
- package/package.json +9 -9
- package/src/data/bucket/fill_extrusion_bucket.ts +1 -13
- package/src/data/bucket/round_polygon_corners.test.ts +84 -36
- package/src/data/bucket/round_polygon_corners.ts +90 -39
- package/src/data/extent_bounds.ts +28 -1
- package/src/geo/projection/globe_transform.test.ts +137 -1
- package/src/geo/projection/globe_transform.ts +1 -0
- package/src/geo/projection/globe_utils.ts +189 -2
- package/src/geo/projection/vertical_perspective_camera_helper.test.ts +24 -0
- package/src/geo/projection/vertical_perspective_camera_helper.ts +11 -10
- package/src/render/image_atlas.test.ts +110 -2
- package/src/render/image_atlas.ts +35 -4
- package/src/render/image_manager.test.ts +66 -1
- package/src/render/image_manager.ts +136 -144
- package/src/render/painter.ts +5 -2
- package/src/render/pattern_atlas.test.ts +131 -0
- package/src/render/pattern_atlas.ts +144 -0
- package/src/shaders/glsl/_prelude.vertex.glsl +8 -8
- package/src/shaders/glsl/_prelude.vertex.glsl.g.ts +1 -1
- package/src/shaders/glsl/color_relief.fragment.glsl +1 -2
- package/src/shaders/glsl/color_relief.fragment.glsl.g.ts +1 -1
- package/src/shaders/glsl/hillshade_prepare.fragment.glsl +12 -12
- package/src/shaders/glsl/hillshade_prepare.fragment.glsl.g.ts +1 -1
- package/src/source/image_source.test.ts +41 -31
- package/src/source/image_source.ts +14 -15
- package/src/source/raster_dem_tile_source.test.ts +37 -3
- package/src/source/raster_dem_tile_source.ts +1 -2
- package/src/source/raster_tile_source.test.ts +5 -26
- package/src/source/raster_tile_source.ts +4 -3
- package/src/style/style.test.ts +64 -0
- package/src/style/style.ts +37 -64
- package/src/symbol/cross_tile_symbol_index.test.ts +31 -0
- package/src/symbol/cross_tile_symbol_index.ts +67 -37
- package/src/tile/tile_manager.test.ts +69 -1
- package/src/tile/tile_manager.ts +14 -9
- package/src/ui/handler/two_fingers_touch.test.ts +14 -3
- package/src/ui/handler_inertia.test.ts +91 -0
- package/src/ui/handler_inertia.ts +65 -14
- package/src/ui/map_tests/map_images.test.ts +26 -0
- package/src/ui/map_tests/map_webgl.test.ts +2 -1
- package/src/ui/marker.test.ts +151 -0
- package/src/ui/marker.ts +120 -10
- package/src/util/dom.test.ts +13 -0
- package/src/util/dom.ts +1 -1
- package/src/util/image_request.ts +31 -1
- package/src/webgl/draw/draw_background.ts +1 -1
- package/src/webgl/program/pattern.ts +3 -3
package/dist/maplibre-gl-dev.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MapLibre GL JS
|
|
3
|
-
* @license 3-Clause BSD. Full text of license: https://github.com/maplibre/maplibre-gl-js/blob/v6.
|
|
3
|
+
* @license 3-Clause BSD. Full text of license: https://github.com/maplibre/maplibre-gl-js/blob/v6.4.1/LICENSE.txt
|
|
4
4
|
*/
|
|
5
|
-
import { $ as
|
|
5
|
+
import { $ as tileCoordinatesToMercatorCoordinates, $n as deepEqual, $r as mul, $t as TRANSITION_SUFFIX, A as evaluateSizeForFeature, Ai as perspective, An as getVideo, Ar as remapSaturate, At as toEvaluationFeature, Bi as invert, Br as wrap, Bt as SegmentVector, C as isCustomStyleLayer, Ci as equals, Cn as Event, Cr as nextPowerOfTwo, Ct as HEATMAP_FULL_RENDER_FBO_KEY, D as SymbolBucket, Di as invert$1, Dn as getArrayBuffer, Dr as radiansToDegrees, Dt as RGBAImage, E as isSymbolStyleLayer, Ei as identity, En as GLOBAL_DISPATCHER_ID, Er as pointPlaneSignedDistance, Et as AlphaImage, F as ImagePosition, Fi as translate, Fn as removeProtocol, Fr as subscribe, Ft as Uniform4f, G as isFillExtrusionStyleLayer, Gn as bezier, Gr as length, Gt as PosArray, H as isLineStyleLayer, Hi as isOffscreenCanvasDistorted, Hn as angleToRotateBetweenVectors2D, Hr as pixelsToTileUnits, Ht as CollisionCircleLayoutArray, I as potpack, Ii as create$4, In as config, Ir as threePlaneIntersection, It as UniformColor, J as cameraDirectionFromPitchBearing, Jn as createIdentityMat4f32, Jr as zero, Jt as TriangleIndexArray, Kn as clamp, Kr as scale$1, Kt as QuadTriangleArray, L as isStyleImageWebGLData, Li as fromRotation, Ln as AbortError, Lr as translatePosition, Lt as UniformColorArray, Mi as rotateY$1, Mn as sameOrigin, Mr as rollPitchBearingToQuat, Mt as Uniform1i, N as getAnchorAlignment, Ni as rotateZ, Nn as addProtocol, Nr as scaleZoom, Nt as Uniform2f, O as addDynamicAttributes, Oi as multiply, On as getJSON, Or as rayPlaneIntersection, Ot as isCircleStyleLayer, Pi as scale, Pn as getProtocol, Pr as sphericalToCartesian, Pt as Uniform3f, Q as projectToWorldCoordinates, Qn as createVec4f64, Qr as slerp, Qt as Properties, R as renderStyleImage, Ri as create$2, Rn as isAbortError, Rr as uniqueId, Rt as UniformFloatArray, S as createStyleLayer, Si as create$1, Sn as ErrorEvent, Sr as mod, St as isHillshadeStyleLayer, T as isBackgroundStyleLayer, Ti as fromScaling, Tn as AJAXError, Tr as pick, Tt as renderColorRamp, Ui as offscreenCanvasSupported, Un as arrayBufferToImage, Ur as EXTENT, Ut as LineStripIndexArray, V as collisionCircleLayout, Vi as rotate, Vn as MAX_VALID_LATITUDE, Vr as zoomScale, Vt as CollisionBoxArray, Wi as Point, Wn as arrayBufferToImageBitmap, Wr as create$3, Wt as Pos3dArray, X as getMercatorHorizon, Xn as createMat4f64, Xr as fromValues, Xt as isRasterStyleLayer, Y as cameraMercatorCoordinateFromCenterAndRotation, Yn as createIdentityMat4f64, Yr as fromEuler, Yt as createLayout, Z as maxMercatorHorizonAngle, Zn as createVec3f64, Zr as multiply$1, Zt as DataConstantProperty, _ as UnwrappedTileID, _i as transformMat4$1, _n as emptyStyle, _r as isTouchableEvent, _t as SubdivisionGranularityExpression, a as clipLine, ai as dot, ar as evaluateZoomSnap, at as mercatorXfromLng, b as isInBoundsForZoomLngLat, bi as clone$1, bn as interpolateFactory, br as lerp, ci as negate, cn as validateAndEmit, cr as findLineIntersection, ct as LngLat, di as rotateY, dn as Color, dr as getEdgeTiles, dt as EXTENT_BOUNDS, ei as scale$3, en as Transitionable, er as defaultEasing, et as unprojectFromWorldCoordinates, f as GEOJSON_TILE_LAYER_NAME, fi as rotateZ$1, fn as ProjectionDefinition, ft as Bounds, g as OverscaledTileID, gi as transformMat3, gn as diff, gr as isSafari, gt as SOUTH_POLE_Y, h as CanonicalTileID, hi as sub, hn as derefLayers, hr as isPointableEvent, ht as NORTH_POLE_Y, ii as cross, in as ZoomHistory, ir as ensureError, it as lngFromMercatorX, j as evaluateSizeForZoom, ji as rotateX, jn as makeRequest, jr as rollPitchBearingEqual, jt as Uniform1f, k as getOverlapMode, ki as ortho, kn as getReferrer, kr as readImageUsingVideoFrame, kt as polygonIntersectsPolygon, li as normalize, ln as validateStyle, lr as getAABB, lt as earthRadius, mi as scaleAndAdd, mr as isImageBitmap, ni as add, nr as differenceOfAnglesDegrees, nt as altitudeFromMercatorZ, oi as len, on as SPEC_SOURCE_TYPES, or as extend, ot as mercatorYfromLat, pi as scale$2, pn as ValidationError, pr as getRollPitchBearing, pt as isFillStyleLayer, q as calculateTileMatrix, qn as clone$2, qr as sqrLen, qt as RasterBoundsArray, r as TextAnchorEnum, ri as clone, rn as codePointUsesLocalIdeographFontFamily, rr as distanceOfAnglesRadians, rt as latFromMercatorY, s as TileCache, si as length$1, sn as emitValidationErrors, sr as filterObject, st as mercatorZfromAltitude, t as getAnchorJustification, ti as transformMat4, tn as EvaluationParameters, tr as degreesToRadians, tt as MercatorCoordinate, u as GeoJSONFeature, ui as rotateX$1, un as validateStyleAndEmit, ur as getAngleDelta, v as calculateTileKey, vi as transformQuat, vn as featureFilter, vr as isTouchableOrPointableType, vt as SubdivisionGranularitySetting, w as validateCustomStyleLayer, wi as exactEquals, wn as Evented, wr as parseCacheControl, wt as isHeatmapStyleLayer, x as Actor, xi as copy, xn as latest, xr as mapObject, xt as Texture, y as compareTileId, yi as zero$1, yr as isWorker, yt as isColorReliefStyleLayer, z as parseGlyphPbf, zi as determinant, zn as throwIfAborted, zr as warnOnce, zt as UniformMatrix4f } from "./maplibre-gl-shared-dev.mjs";
|
|
6
6
|
//#region package.json
|
|
7
|
-
var version$2 = "6.
|
|
7
|
+
var version$2 = "6.4.1";
|
|
8
8
|
//#endregion
|
|
9
9
|
//#region src/util/browser.ts
|
|
10
10
|
let linkEl;
|
|
@@ -288,7 +288,7 @@ var DOM = class DOM {
|
|
|
288
288
|
* @param elem - The element
|
|
289
289
|
*/
|
|
290
290
|
static removeAttributes(elem) {
|
|
291
|
-
for (const { name, value } of elem.attributes) {
|
|
291
|
+
for (const { name, value } of Array.from(elem.attributes)) {
|
|
292
292
|
if (!DOM.isPossiblyDangerous(name, value)) continue;
|
|
293
293
|
elem.removeAttribute(name);
|
|
294
294
|
}
|
|
@@ -326,6 +326,12 @@ let ImageRequest;
|
|
|
326
326
|
for (const key of Object.keys(throttleControlCallbacks)) if (throttleControlCallbacks[key]()) return true;
|
|
327
327
|
return false;
|
|
328
328
|
};
|
|
329
|
+
async function transformAndGetImage(requestManager, url, resourceType, abortController, supportImageRefresh = true, imageBitmapOptions) {
|
|
330
|
+
const requestParameters = await requestManager.transformRequest(url, resourceType);
|
|
331
|
+
throwIfAborted(abortController.signal);
|
|
332
|
+
return ImageRequest.getImage(requestParameters, abortController, supportImageRefresh, imageBitmapOptions);
|
|
333
|
+
}
|
|
334
|
+
_ImageRequest.transformAndGetImage = transformAndGetImage;
|
|
329
335
|
_ImageRequest.getImage = (requestParameters, abortController, supportImageRefresh = true, imageBitmapOptions) => {
|
|
330
336
|
return new Promise((resolve, reject) => {
|
|
331
337
|
requestParameters.headers ||= {};
|
|
@@ -754,51 +760,25 @@ async function doOnceCompleted(jsonsMap, imagesMap) {
|
|
|
754
760
|
//#endregion
|
|
755
761
|
//#region src/render/image_manager.ts
|
|
756
762
|
/**
|
|
757
|
-
*
|
|
758
|
-
*
|
|
759
|
-
*
|
|
760
|
-
* correct behavior of GL_LINEAR texture sampling mode.
|
|
761
|
-
*/
|
|
762
|
-
const padding = 1;
|
|
763
|
-
/**
|
|
764
|
-
* ImageManager does three things:
|
|
765
|
-
*
|
|
766
|
-
* 1. Tracks requests for icon images from tile workers and sends responses when the requests are fulfilled.
|
|
767
|
-
* 2. Builds a texture atlas for pattern images.
|
|
768
|
-
* 3. Rerenders renderable images once per frame
|
|
769
|
-
*
|
|
770
|
-
* These are disparate responsibilities and should eventually be handled by different classes. When we implement
|
|
771
|
-
* data-driven support for `*-pattern`, we'll likely use per-bucket pattern atlases, and that would be a good time
|
|
772
|
-
* to refactor this.
|
|
763
|
+
* Owns every image of the style - the ones the sprites bring in as well as the ones added at
|
|
764
|
+
* runtime - and tracks requests for them from the tile workers, sending responses when the
|
|
765
|
+
* requests are fulfilled.
|
|
773
766
|
*/
|
|
774
767
|
var ImageManager = class extends Evented {
|
|
775
768
|
constructor() {
|
|
776
769
|
super();
|
|
777
770
|
this.images = {};
|
|
778
|
-
this.
|
|
779
|
-
this.callbackDispatchedThisFrame = {};
|
|
771
|
+
this.updateVersion = 0;
|
|
780
772
|
this.loaded = false;
|
|
781
773
|
this.requestors = [];
|
|
782
774
|
this.missingImageResolver = null;
|
|
783
|
-
this.
|
|
784
|
-
this.
|
|
785
|
-
|
|
786
|
-
height: 1
|
|
787
|
-
});
|
|
788
|
-
this.dirty = true;
|
|
775
|
+
this._spriteImagesIds = {};
|
|
776
|
+
this._imagesIds = null;
|
|
777
|
+
this._renderCallbacksDispatchedThisFrame = {};
|
|
789
778
|
}
|
|
790
779
|
destroy() {
|
|
791
|
-
if (this.atlasTexture) {
|
|
792
|
-
this.atlasTexture.destroy();
|
|
793
|
-
this.atlasTexture = null;
|
|
794
|
-
}
|
|
795
780
|
for (const id of Object.keys(this.images)) this.removeImage(id);
|
|
796
|
-
this.
|
|
797
|
-
this.atlasImage = new RGBAImage({
|
|
798
|
-
width: 1,
|
|
799
|
-
height: 1
|
|
800
|
-
});
|
|
801
|
-
this.dirty = true;
|
|
781
|
+
this._spriteImagesIds = {};
|
|
802
782
|
}
|
|
803
783
|
isLoaded() {
|
|
804
784
|
return this.loaded;
|
|
@@ -827,6 +807,7 @@ var ImageManager = class extends Evented {
|
|
|
827
807
|
if (this.images[id]) throw new Error(`Image id ${id} already exist, use updateImage instead`);
|
|
828
808
|
if (this._validate(id, image)) {
|
|
829
809
|
this.images[id] = image;
|
|
810
|
+
this._imagesIds = null;
|
|
830
811
|
if (image.isWebGLImage) this.updateImage(id, image, false);
|
|
831
812
|
}
|
|
832
813
|
}
|
|
@@ -869,21 +850,97 @@ var ImageManager = class extends Evented {
|
|
|
869
850
|
if (content[2] < content[0]) return false;
|
|
870
851
|
return content[3] >= content[1];
|
|
871
852
|
}
|
|
853
|
+
/**
|
|
854
|
+
* Replaces an image that is already known under this id, bumping its version so that the
|
|
855
|
+
* atlases holding it notice.
|
|
856
|
+
*
|
|
857
|
+
* The old record is read directly rather than through {@link ImageManager.getImage}, which
|
|
858
|
+
* would force a synchronous decode of the sprite data of the very image being replaced. Its
|
|
859
|
+
* size therefore comes from whichever of the two the pixels are still in, since an image that
|
|
860
|
+
* came from a sprite and was never rendered has not been decoded yet, and its version is
|
|
861
|
+
* defaulted, since images start out without one.
|
|
862
|
+
*
|
|
863
|
+
* @param validate - whether to reject an image of a different size than the one it replaces
|
|
864
|
+
*/
|
|
872
865
|
updateImage(id, image, validate = true) {
|
|
873
|
-
const oldImage = this.
|
|
874
|
-
if (validate
|
|
875
|
-
|
|
866
|
+
const oldImage = this.images[id];
|
|
867
|
+
if (validate) {
|
|
868
|
+
const oldData = oldImage.data || oldImage.spriteData;
|
|
869
|
+
if (oldData.width !== image.data.width || oldData.height !== image.data.height) throw new Error(`size mismatch between old image (${oldData.width}x${oldData.height}) and new image (${image.data.width}x${image.data.height}).`);
|
|
870
|
+
}
|
|
871
|
+
image.version = (oldImage.version ?? 0) + 1;
|
|
876
872
|
this.images[id] = image;
|
|
877
|
-
this.
|
|
873
|
+
this.updateVersion++;
|
|
878
874
|
}
|
|
879
875
|
removeImage(id) {
|
|
880
876
|
const image = this.images[id];
|
|
877
|
+
if (!image) return;
|
|
881
878
|
delete this.images[id];
|
|
882
|
-
|
|
879
|
+
this._imagesIds = null;
|
|
883
880
|
if (image.userImage?.onRemove) image.userImage.onRemove();
|
|
884
881
|
}
|
|
882
|
+
/**
|
|
883
|
+
* @returns the ids of every image currently held, sprite images and runtime ones alike. The
|
|
884
|
+
* returned array is shared between callers and must not be modified.
|
|
885
|
+
*/
|
|
885
886
|
listImages() {
|
|
886
|
-
|
|
887
|
+
this._imagesIds ??= Object.keys(this.images);
|
|
888
|
+
return this._imagesIds;
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Images of the `default` sprite keep their plain id, the ones of any other sprite are
|
|
892
|
+
* namespaced by their sprite's id.
|
|
893
|
+
*/
|
|
894
|
+
_getSpriteImageId(spriteId, imageId) {
|
|
895
|
+
return spriteId === "default" ? imageId : `${spriteId}:${imageId}`;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Takes over the images of a single sprite: adds the new ones, updates the ones that are
|
|
899
|
+
* already known, and removes the ones that a previous load of this same sprite had brought in
|
|
900
|
+
* but that are not part of it anymore.
|
|
901
|
+
*
|
|
902
|
+
* @param spriteId - the id of the sprite the images belong to
|
|
903
|
+
* @param images - the sprite's images, keyed by their id within the sprite
|
|
904
|
+
* @returns the ids of the images that this sprite now provides, and the ids of the ones that
|
|
905
|
+
* were removed because they are no longer part of it
|
|
906
|
+
*/
|
|
907
|
+
setSpriteImages(spriteId, images) {
|
|
908
|
+
const previousIds = this._spriteImagesIds[spriteId] ?? [];
|
|
909
|
+
const loaded = [];
|
|
910
|
+
for (const id in images) {
|
|
911
|
+
const imageId = this._getSpriteImageId(spriteId, id);
|
|
912
|
+
loaded.push(imageId);
|
|
913
|
+
if (imageId in this.images) this.updateImage(imageId, images[id], false);
|
|
914
|
+
else this.addImage(imageId, images[id]);
|
|
915
|
+
}
|
|
916
|
+
const loadedIds = new Set(loaded);
|
|
917
|
+
const removed = previousIds.filter((imageId) => !loadedIds.has(imageId));
|
|
918
|
+
for (const imageId of removed) this.removeImage(imageId);
|
|
919
|
+
this._spriteImagesIds[spriteId] = loaded;
|
|
920
|
+
return {
|
|
921
|
+
loaded,
|
|
922
|
+
removed
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
/**
|
|
926
|
+
* Removes all the images a single sprite has brought in.
|
|
927
|
+
* @returns the ids of the removed images
|
|
928
|
+
*/
|
|
929
|
+
removeSpriteImages(spriteId) {
|
|
930
|
+
const removed = this._spriteImagesIds[spriteId] ?? [];
|
|
931
|
+
for (const imageId of removed) this.removeImage(imageId);
|
|
932
|
+
delete this._spriteImagesIds[spriteId];
|
|
933
|
+
return removed;
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* Removes the images of every sprite, leaving the images added at runtime alone.
|
|
937
|
+
* @returns the ids of the removed images
|
|
938
|
+
*/
|
|
939
|
+
removeAllSpriteImages() {
|
|
940
|
+
const removed = Object.values(this._spriteImagesIds).flat();
|
|
941
|
+
for (const imageId of removed) this.removeImage(imageId);
|
|
942
|
+
this._spriteImagesIds = {};
|
|
943
|
+
return removed;
|
|
887
944
|
}
|
|
888
945
|
setMissingImageResolver(resolver) {
|
|
889
946
|
this.missingImageResolver = resolver;
|
|
@@ -904,7 +961,7 @@ var ImageManager = class extends Evented {
|
|
|
904
961
|
async _getImagesForIds(ids) {
|
|
905
962
|
const unresolvedIds = new Set(ids.filter((id) => !this.getImage(id)));
|
|
906
963
|
const resolver = this.missingImageResolver;
|
|
907
|
-
if (resolver) await Promise.
|
|
964
|
+
if (resolver) await Promise.allSettled(Array.from(unresolvedIds, (id) => resolver(id)));
|
|
908
965
|
const response = {};
|
|
909
966
|
for (const id of ids) {
|
|
910
967
|
const image = this.getImage(id);
|
|
@@ -931,57 +988,126 @@ var ImageManager = class extends Evented {
|
|
|
931
988
|
}
|
|
932
989
|
return response;
|
|
933
990
|
}
|
|
991
|
+
beginFrame() {
|
|
992
|
+
this._renderCallbacksDispatchedThisFrame = {};
|
|
993
|
+
}
|
|
994
|
+
/**
|
|
995
|
+
* Re-renders the images among `ids` that were added with a `render` callback (see
|
|
996
|
+
* `StyleImageInterface`), at most once per frame each.
|
|
997
|
+
*/
|
|
998
|
+
dispatchRenderCallbacks(ids) {
|
|
999
|
+
for (const id of ids) {
|
|
1000
|
+
if (this._renderCallbacksDispatchedThisFrame[id]) continue;
|
|
1001
|
+
this._renderCallbacksDispatchedThisFrame[id] = true;
|
|
1002
|
+
const image = this.getImage(id);
|
|
1003
|
+
if (!image) warnOnce(`Image with ID: "${id}" was not found`);
|
|
1004
|
+
if (renderStyleImage(image)) this.updateImage(id, image);
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
cloneImages() {
|
|
1008
|
+
const clonedImages = {};
|
|
1009
|
+
for (const id in this.images) {
|
|
1010
|
+
const image = this.images[id];
|
|
1011
|
+
clonedImages[id] = {
|
|
1012
|
+
...image,
|
|
1013
|
+
data: image.data ? image.data.clone() : null
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
return clonedImages;
|
|
1017
|
+
}
|
|
1018
|
+
};
|
|
1019
|
+
//#endregion
|
|
1020
|
+
//#region src/render/pattern_atlas.ts
|
|
1021
|
+
/**
|
|
1022
|
+
* When copied into the atlas texture, pattern images are padded by one pixel on each side with a
|
|
1023
|
+
* copy of the image data wrapped from the opposite side. This ensures the correct behavior of
|
|
1024
|
+
* GL_LINEAR texture sampling mode.
|
|
1025
|
+
*/
|
|
1026
|
+
const PADDING = 1;
|
|
1027
|
+
/**
|
|
1028
|
+
* A texture atlas of the pattern images that are drawn without a tile's own {@link ImageAtlas},
|
|
1029
|
+
* i.e. `background-pattern`. Entries are packed on demand and re-packed whenever one of them is
|
|
1030
|
+
* added or changes, which is rare enough for the repacking cost not to matter.
|
|
1031
|
+
*/
|
|
1032
|
+
var PatternAtlas = class {
|
|
1033
|
+
constructor(imageManager) {
|
|
1034
|
+
this._imageManager = imageManager;
|
|
1035
|
+
this._entries = {};
|
|
1036
|
+
this._image = new RGBAImage({
|
|
1037
|
+
width: 1,
|
|
1038
|
+
height: 1
|
|
1039
|
+
});
|
|
1040
|
+
this._dirty = true;
|
|
1041
|
+
}
|
|
1042
|
+
destroy() {
|
|
1043
|
+
if (this._texture) {
|
|
1044
|
+
this._texture.destroy();
|
|
1045
|
+
this._texture = null;
|
|
1046
|
+
}
|
|
1047
|
+
this._entries = {};
|
|
1048
|
+
this._image = new RGBAImage({
|
|
1049
|
+
width: 1,
|
|
1050
|
+
height: 1
|
|
1051
|
+
});
|
|
1052
|
+
this._dirty = true;
|
|
1053
|
+
}
|
|
934
1054
|
getPixelSize() {
|
|
935
|
-
const { width, height } = this.
|
|
1055
|
+
const { width, height } = this._image;
|
|
936
1056
|
return {
|
|
937
1057
|
width,
|
|
938
1058
|
height
|
|
939
1059
|
};
|
|
940
1060
|
}
|
|
1061
|
+
/**
|
|
1062
|
+
* @returns the position of the pattern within the atlas, or `null` if there is no such image
|
|
1063
|
+
*/
|
|
941
1064
|
getPattern(id) {
|
|
942
|
-
const
|
|
943
|
-
const image = this.getImage(id);
|
|
1065
|
+
const image = this._imageManager.getImage(id);
|
|
944
1066
|
if (!image) return null;
|
|
945
|
-
|
|
946
|
-
if (
|
|
1067
|
+
const entry = this._entries[id];
|
|
1068
|
+
if (entry?.image !== image) {
|
|
947
1069
|
const bin = {
|
|
948
1070
|
w: image.data.width + 2,
|
|
949
1071
|
h: image.data.height + 2,
|
|
950
1072
|
x: 0,
|
|
951
1073
|
y: 0
|
|
952
1074
|
};
|
|
953
|
-
|
|
954
|
-
this.patterns[id] = {
|
|
1075
|
+
this._entries[id] = {
|
|
955
1076
|
bin,
|
|
956
|
-
position
|
|
1077
|
+
position: new ImagePosition(bin, image),
|
|
1078
|
+
image
|
|
957
1079
|
};
|
|
958
|
-
} else
|
|
959
|
-
|
|
960
|
-
|
|
1080
|
+
} else if (entry.position.version !== image.version) entry.position.version = image.version;
|
|
1081
|
+
else return entry.position;
|
|
1082
|
+
this._update();
|
|
1083
|
+
return this._entries[id].position;
|
|
961
1084
|
}
|
|
962
1085
|
bind(context) {
|
|
963
1086
|
const gl = context.gl;
|
|
964
|
-
if (!this.
|
|
965
|
-
|
|
966
|
-
this.
|
|
967
|
-
|
|
1087
|
+
if (!this._texture) {
|
|
1088
|
+
this._texture = new Texture(context, this._image, gl.RGBA);
|
|
1089
|
+
this._dirty = false;
|
|
1090
|
+
} else if (this._dirty) {
|
|
1091
|
+
this._texture.update(this._image);
|
|
1092
|
+
this._dirty = false;
|
|
968
1093
|
}
|
|
969
|
-
this.
|
|
1094
|
+
this._texture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
|
|
970
1095
|
}
|
|
971
|
-
|
|
1096
|
+
_update() {
|
|
1097
|
+
for (const id in this._entries) if (!this._imageManager.getImage(id)) delete this._entries[id];
|
|
972
1098
|
const bins = [];
|
|
973
|
-
for (const id in this.
|
|
1099
|
+
for (const id in this._entries) bins.push(this._entries[id].bin);
|
|
974
1100
|
const { w, h } = potpack(bins);
|
|
975
|
-
const dst = this.
|
|
1101
|
+
const dst = this._image;
|
|
976
1102
|
dst.resize({
|
|
977
1103
|
width: w || 1,
|
|
978
1104
|
height: h || 1
|
|
979
1105
|
});
|
|
980
|
-
for (const id in this.
|
|
981
|
-
const { bin } = this.
|
|
982
|
-
const x = bin.x +
|
|
983
|
-
const y = bin.y +
|
|
984
|
-
const src = this.
|
|
1106
|
+
for (const id in this._entries) {
|
|
1107
|
+
const { bin } = this._entries[id];
|
|
1108
|
+
const x = bin.x + PADDING;
|
|
1109
|
+
const y = bin.y + PADDING;
|
|
1110
|
+
const src = this._entries[id].image.data;
|
|
985
1111
|
const w = src.width;
|
|
986
1112
|
const h = src.height;
|
|
987
1113
|
RGBAImage.copy(src, dst, {
|
|
@@ -1035,30 +1161,7 @@ var ImageManager = class extends Evented {
|
|
|
1035
1161
|
height: h
|
|
1036
1162
|
});
|
|
1037
1163
|
}
|
|
1038
|
-
this.
|
|
1039
|
-
}
|
|
1040
|
-
beginFrame() {
|
|
1041
|
-
this.callbackDispatchedThisFrame = {};
|
|
1042
|
-
}
|
|
1043
|
-
dispatchRenderCallbacks(ids) {
|
|
1044
|
-
for (const id of ids) {
|
|
1045
|
-
if (this.callbackDispatchedThisFrame[id]) continue;
|
|
1046
|
-
this.callbackDispatchedThisFrame[id] = true;
|
|
1047
|
-
const image = this.getImage(id);
|
|
1048
|
-
if (!image) warnOnce(`Image with ID: "${id}" was not found`);
|
|
1049
|
-
if (renderStyleImage(image)) this.updateImage(id, image);
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
cloneImages() {
|
|
1053
|
-
const clonedImages = {};
|
|
1054
|
-
for (const id in this.images) {
|
|
1055
|
-
const image = this.images[id];
|
|
1056
|
-
clonedImages[id] = {
|
|
1057
|
-
...image,
|
|
1058
|
-
data: image.data ? image.data.clone() : null
|
|
1059
|
-
};
|
|
1060
|
-
}
|
|
1061
|
-
return clonedImages;
|
|
1164
|
+
this._dirty = true;
|
|
1062
1165
|
}
|
|
1063
1166
|
};
|
|
1064
1167
|
//#endregion
|
|
@@ -2790,10 +2893,9 @@ var RasterTileSource = class extends Evented {
|
|
|
2790
2893
|
const url = tile.tileID.canonical.url(this.tiles, this.map.getPixelRatio(), this.scheme);
|
|
2791
2894
|
const premultiply = this._premultiplyAlpha;
|
|
2792
2895
|
const imageBitmapOptions = premultiply ? void 0 : { premultiplyAlpha: "none" };
|
|
2793
|
-
const request = await this.map._requestManager.transformRequest(url, "Tile");
|
|
2794
2896
|
tile.abortController = new AbortController();
|
|
2795
2897
|
try {
|
|
2796
|
-
const response = await ImageRequest.
|
|
2898
|
+
const response = await ImageRequest.transformAndGetImage(this.map._requestManager, url, "Tile", tile.abortController, this.map._refreshExpiredTiles, imageBitmapOptions);
|
|
2797
2899
|
delete tile.abortController;
|
|
2798
2900
|
if (tile.aborted) {
|
|
2799
2901
|
tile.state = "unloaded";
|
|
@@ -2875,11 +2977,10 @@ var RasterDEMTileSource = class extends RasterTileSource {
|
|
|
2875
2977
|
}
|
|
2876
2978
|
async loadTile(tile) {
|
|
2877
2979
|
const url = tile.tileID.canonical.url(this.tiles, this.map.getPixelRatio(), this.scheme);
|
|
2878
|
-
const request = await this.map._requestManager.transformRequest(url, "Tile");
|
|
2879
2980
|
tile.neighboringTiles = this._getNeighboringTiles(tile.tileID);
|
|
2880
2981
|
tile.abortController = new AbortController();
|
|
2881
2982
|
try {
|
|
2882
|
-
const response = await ImageRequest.
|
|
2983
|
+
const response = await ImageRequest.transformAndGetImage(this.map._requestManager, url, "Tile", tile.abortController, this.map._refreshExpiredTiles, { colorSpaceConversion: "none" });
|
|
2883
2984
|
delete tile.abortController;
|
|
2884
2985
|
if (tile.aborted) {
|
|
2885
2986
|
tile.state = "unloaded";
|
|
@@ -3847,11 +3948,10 @@ var ImageSource = class extends Evented {
|
|
|
3847
3948
|
this._loaded = false;
|
|
3848
3949
|
this.fire(new MapSourceDataEvent("dataloading"));
|
|
3849
3950
|
this.url = this.options.url;
|
|
3850
|
-
|
|
3851
|
-
this._request = new AbortController();
|
|
3951
|
+
this._abortController = new AbortController();
|
|
3852
3952
|
try {
|
|
3853
|
-
const image = await ImageRequest.
|
|
3854
|
-
this.
|
|
3953
|
+
const image = await ImageRequest.transformAndGetImage(this.map._requestManager, this.url, "Image", this._abortController);
|
|
3954
|
+
this._abortController = null;
|
|
3855
3955
|
this._loaded = true;
|
|
3856
3956
|
if (image?.data) {
|
|
3857
3957
|
this._setImage(image.data);
|
|
@@ -3859,9 +3959,10 @@ var ImageSource = class extends Evented {
|
|
|
3859
3959
|
this._finishLoading();
|
|
3860
3960
|
}
|
|
3861
3961
|
} catch (err) {
|
|
3862
|
-
|
|
3962
|
+
if (isAbortError(err)) return;
|
|
3963
|
+
this._abortController = null;
|
|
3863
3964
|
this._loaded = true;
|
|
3864
|
-
|
|
3965
|
+
this.fire(new ErrorEvent(ensureError(err)));
|
|
3865
3966
|
}
|
|
3866
3967
|
}
|
|
3867
3968
|
loaded() {
|
|
@@ -3878,9 +3979,9 @@ var ImageSource = class extends Evented {
|
|
|
3878
3979
|
* @param options - The options object.
|
|
3879
3980
|
*/
|
|
3880
3981
|
updateImage(options) {
|
|
3881
|
-
if (this.
|
|
3882
|
-
this.
|
|
3883
|
-
this.
|
|
3982
|
+
if (this._abortController) {
|
|
3983
|
+
this._abortController.abort();
|
|
3984
|
+
this._abortController = null;
|
|
3884
3985
|
}
|
|
3885
3986
|
if ("image" in options) {
|
|
3886
3987
|
this._loaded = true;
|
|
@@ -3915,9 +4016,9 @@ var ImageSource = class extends Evented {
|
|
|
3915
4016
|
this.load();
|
|
3916
4017
|
}
|
|
3917
4018
|
onRemove() {
|
|
3918
|
-
if (this.
|
|
3919
|
-
this.
|
|
3920
|
-
this.
|
|
4019
|
+
if (this._abortController) {
|
|
4020
|
+
this._abortController.abort();
|
|
4021
|
+
this._abortController = null;
|
|
3921
4022
|
}
|
|
3922
4023
|
this._disposeTexture();
|
|
3923
4024
|
this.image = null;
|
|
@@ -5140,12 +5241,6 @@ function coveringTiles(transform, options) {
|
|
|
5140
5241
|
return result.sort((a, b) => a.distanceSq - b.distanceSq).map((a) => a.tileID);
|
|
5141
5242
|
}
|
|
5142
5243
|
//#endregion
|
|
5143
|
-
//#region src/data/extent_bounds.ts
|
|
5144
|
-
/**
|
|
5145
|
-
* The bounding box covering the entire extent of a tile.
|
|
5146
|
-
*/
|
|
5147
|
-
const EXTENT_BOUNDS = Bounds.fromPoints([new Point(0, 0), new Point(EXTENT, EXTENT)]);
|
|
5148
|
-
//#endregion
|
|
5149
5244
|
//#region src/tile/tile_manager_raster.ts
|
|
5150
5245
|
function isRasterType(type) {
|
|
5151
5246
|
return type === "raster" || type === "image" || type === "video";
|
|
@@ -5463,10 +5558,10 @@ var TileManager = class TileManager extends Evented {
|
|
|
5463
5558
|
if (shouldReload) this.reload();
|
|
5464
5559
|
if (this.transform) this.update(this.transform, this.terrain);
|
|
5465
5560
|
}
|
|
5466
|
-
async _loadTile(tile, id, state) {
|
|
5561
|
+
async _loadTile(tile, id, state, hadData) {
|
|
5467
5562
|
try {
|
|
5468
5563
|
const result = await this._source.loadTile(tile);
|
|
5469
|
-
this._tileLoaded(tile, id, state, result);
|
|
5564
|
+
this._tileLoaded(tile, id, state, hadData, result);
|
|
5470
5565
|
} catch (err) {
|
|
5471
5566
|
tile.state = "errored";
|
|
5472
5567
|
if (err.status !== 404) this._source.fire(new ErrorEvent(ensureError(err), { tile }));
|
|
@@ -5532,12 +5627,15 @@ var TileManager = class TileManager extends Evented {
|
|
|
5532
5627
|
async _reloadTile(id, state) {
|
|
5533
5628
|
const tile = this._inViewTiles.getTileById(id);
|
|
5534
5629
|
if (!tile) return;
|
|
5630
|
+
const hadData = tile.hasData();
|
|
5535
5631
|
if (tile.state !== "loading") tile.state = state;
|
|
5536
|
-
await this._loadTile(tile, id, state);
|
|
5632
|
+
await this._loadTile(tile, id, state, hadData);
|
|
5537
5633
|
}
|
|
5538
|
-
_tileLoaded(tile, id, previousState, result) {
|
|
5539
|
-
|
|
5540
|
-
|
|
5634
|
+
_tileLoaded(tile, id, previousState, hadData, result) {
|
|
5635
|
+
if (!hadData) {
|
|
5636
|
+
tile.timeAdded = now();
|
|
5637
|
+
if (tile.selfFading) tile.fadeEndTime = tile.timeAdded + this._rasterFadeDuration;
|
|
5638
|
+
}
|
|
5541
5639
|
if (previousState === "expired") tile.refreshedUponExpiration = true;
|
|
5542
5640
|
this._setTileReloadTimer(id, tile);
|
|
5543
5641
|
if (result?.unmodified) return;
|
|
@@ -5788,7 +5886,7 @@ var TileManager = class TileManager extends Evented {
|
|
|
5788
5886
|
const cached = tile;
|
|
5789
5887
|
if (!tile) {
|
|
5790
5888
|
tile = new Tile(tileID, this._source.tileSize * tileID.overscaleFactor());
|
|
5791
|
-
this._loadTile(tile, tileID.key, tile.state);
|
|
5889
|
+
this._loadTile(tile, tileID.key, tile.state, false);
|
|
5792
5890
|
}
|
|
5793
5891
|
tile.uses++;
|
|
5794
5892
|
this._inViewTiles.setTile(tileID.key, tile);
|
|
@@ -8284,24 +8382,54 @@ var TileLayerIndex = class {
|
|
|
8284
8382
|
const entry = this._symbolsByKey[symbolInstance.key];
|
|
8285
8383
|
if (!entry) continue;
|
|
8286
8384
|
const scaledSymbolCoord = this.getScaledCoordinates(symbolInstance, newTileID);
|
|
8287
|
-
if (entry.index)
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
8385
|
+
if (entry.index) this.findMatchesForIndexedEntry(entry, symbolInstance, scaledSymbolCoord, tolerance, zoomCrossTileIDs);
|
|
8386
|
+
else if (entry.positions) this.findMatchesForNonIndexedEntry(entry, symbolInstance, scaledSymbolCoord, tolerance, zoomCrossTileIDs);
|
|
8387
|
+
}
|
|
8388
|
+
}
|
|
8389
|
+
/**
|
|
8390
|
+
* Matches a symbol instance against an entry backed by a KDBush spatial index
|
|
8391
|
+
* (used for keys with more than {@link KDBUSH_THRESHHOLD} symbols).
|
|
8392
|
+
*
|
|
8393
|
+
* Matches any symbol with the same key whose coordinates are within one grid
|
|
8394
|
+
* unit (with a 4px grid, this covers a 12px by 12px area). The lowest-index
|
|
8395
|
+
* unclaimed candidate is claimed in a single pass rather than sorting the
|
|
8396
|
+
* whole result set on every query: `range()` can return many candidates where
|
|
8397
|
+
* symbols are coincident (e.g. stacked point markers), so a per-query sort
|
|
8398
|
+
* would dominate placement cost on dense layers.
|
|
8399
|
+
*
|
|
8400
|
+
* Once a symbol is marked duplicate against a parent symbol, no other symbol
|
|
8401
|
+
* at the same zoom level may duplicate against the same parent (see issue #5993).
|
|
8402
|
+
*/
|
|
8403
|
+
findMatchesForIndexedEntry(entry, symbolInstance, scaledSymbolCoord, tolerance, zoomCrossTileIDs) {
|
|
8404
|
+
const indexes = entry.index.range(scaledSymbolCoord.x - tolerance, scaledSymbolCoord.y - tolerance, scaledSymbolCoord.x + tolerance, scaledSymbolCoord.y + tolerance);
|
|
8405
|
+
let bestIndex = Infinity;
|
|
8406
|
+
for (const candidate of indexes) if (candidate < bestIndex && !zoomCrossTileIDs[entry.crossTileIDs[candidate]]) bestIndex = candidate;
|
|
8407
|
+
if (bestIndex !== Infinity) {
|
|
8408
|
+
const crossTileID = entry.crossTileIDs[bestIndex];
|
|
8409
|
+
zoomCrossTileIDs[crossTileID] = true;
|
|
8410
|
+
symbolInstance.crossTileID = crossTileID;
|
|
8411
|
+
}
|
|
8412
|
+
}
|
|
8413
|
+
/**
|
|
8414
|
+
* Matches a symbol instance against an entry that stores its positions as a
|
|
8415
|
+
* plain array (used for keys with at most {@link KDBUSH_THRESHHOLD} symbols).
|
|
8416
|
+
*
|
|
8417
|
+
* Matches any symbol with the same key whose coordinates are within one grid
|
|
8418
|
+
* unit (with a 4px grid, this covers a 12px by 12px area). Positions are
|
|
8419
|
+
* stored in symbol-instance order, so the first unclaimed match is also the
|
|
8420
|
+
* lowest-index one.
|
|
8421
|
+
*
|
|
8422
|
+
* Once a symbol is marked duplicate against a parent symbol, no other symbol
|
|
8423
|
+
* at the same zoom level may duplicate against the same parent (see issue #5993).
|
|
8424
|
+
*/
|
|
8425
|
+
findMatchesForNonIndexedEntry(entry, symbolInstance, scaledSymbolCoord, tolerance, zoomCrossTileIDs) {
|
|
8426
|
+
for (let i = 0; i < entry.positions.length; i++) {
|
|
8427
|
+
const thisTileSymbol = entry.positions[i];
|
|
8428
|
+
const crossTileID = entry.crossTileIDs[i];
|
|
8429
|
+
if (Math.abs(thisTileSymbol.x - scaledSymbolCoord.x) <= tolerance && Math.abs(thisTileSymbol.y - scaledSymbolCoord.y) <= tolerance && !zoomCrossTileIDs[crossTileID]) {
|
|
8430
|
+
zoomCrossTileIDs[crossTileID] = true;
|
|
8431
|
+
symbolInstance.crossTileID = crossTileID;
|
|
8432
|
+
break;
|
|
8305
8433
|
}
|
|
8306
8434
|
}
|
|
8307
8435
|
}
|
|
@@ -8423,7 +8551,7 @@ var CrossTileSymbolIndex = class {
|
|
|
8423
8551
|
var _prelude_fragment_glsl_g_default = "#ifdef GL_ES\nprecision mediump float;\n#else\n#if !defined(lowp)\n#define lowp\n#endif\n#if !defined(mediump)\n#define mediump\n#endif\n#if !defined(highp)\n#define highp\n#endif\n#endif\nout highp vec4 fragColor;";
|
|
8424
8552
|
//#endregion
|
|
8425
8553
|
//#region src/shaders/glsl/_prelude.vertex.glsl.g.ts
|
|
8426
|
-
var _prelude_vertex_glsl_g_default = "#ifdef GL_ES\nprecision highp float;\n#else\n#if !defined(lowp)\n#define lowp\n#endif\n#if !defined(mediump)\n#define mediump\n#endif\n#if !defined(highp)\n#define highp\n#endif\n#endif\nvec2 unpack_float(const float packedValue) {int packedIntValue=int(packedValue);int v0=packedIntValue/256;return vec2(v0,packedIntValue-v0*256);}vec2 unpack_opacity(const uint packedOpacity) {return vec2(float(packedOpacity >> 1u)/127.0,float(packedOpacity & 1u));}vec4 decode_color(const vec2 encodedColor) {return vec4(unpack_float(encodedColor[0])/255.0,unpack_float(encodedColor[1])/255.0\n);}float unpack_mix_vec2(const vec2 packedValue,const float t) {return mix(packedValue[0],packedValue[1],t);}vec4 unpack_mix_color(const vec4 packedColors,const float t) {vec4 minColor=decode_color(vec2(packedColors[0],packedColors[1]));vec4 maxColor=decode_color(vec2(packedColors[2],packedColors[3]));return mix(minColor,maxColor,t);}vec2 get_pattern_pos(const vec2 pixel_coord_upper,const vec2 pixel_coord_lower,const vec2 pattern_size,const float tile_units_to_pixels,const vec2 pos) {vec2 offset=mod(mod(mod(pixel_coord_upper,pattern_size)*256.0,pattern_size)*256.0+pixel_coord_lower,pattern_size);return (tile_units_to_pixels*pos+offset)/pattern_size;}mat3 rotationMatrixFromAxisAngle(vec3 u,float angle) {float c=cos(angle);float s=sin(angle);float c2=1.0-c;return mat3(u.x*u.x*c2+ c,u.x*u.y*c2-u.z*s,u.x*u.z*c2+u.y*s,u.y*u.x*c2+u.z*s,u.y*u.y*c2+ c,u.y*u.z*c2-u.x*s,u.z*u.x*c2-u.y*s,u.z*u.y*c2+u.x*s,u.z*u.z*c2+ c\n);}\n#ifdef TERRAIN3D\nuniform sampler2D u_terrain;uniform float u_terrain_dim;uniform mat4 u_terrain_matrix;uniform vec4 u_terrain_unpack;uniform float u_terrain_exaggeration;uniform highp sampler2D u_depth;\n#endif\nconst highp vec4 bitSh=vec4(256.*256.*256.,256.*256.,256.,1.);const highp vec4 bitShifts=vec4(1.)/bitSh;highp float unpack(highp vec4 color) {return dot(color,bitShifts);}highp float depthOpacity(vec3 frag) {\n#ifdef TERRAIN3D\nhighp float d=unpack(texture(u_depth,frag.xy*0.5+0.5))+0.0001-frag.z;return 1.0-max(0.0,min(1.0,-d*500.0));\n#else\nreturn 1.0;\n#endif\n}float calculate_visibility(vec4 pos) {\n#ifdef TERRAIN3D\nvec3 frag=pos.xyz/pos.w;highp float d=depthOpacity(frag);if (d > 0.95) return 1.0;return (d+depthOpacity(frag+vec3(0.0,0.01,0.0)))/2.0;\n#else\nreturn 1.0;\n#endif\n}float ele(
|
|
8554
|
+
var _prelude_vertex_glsl_g_default = "#ifdef GL_ES\nprecision highp float;\n#else\n#if !defined(lowp)\n#define lowp\n#endif\n#if !defined(mediump)\n#define mediump\n#endif\n#if !defined(highp)\n#define highp\n#endif\n#endif\nvec2 unpack_float(const float packedValue) {int packedIntValue=int(packedValue);int v0=packedIntValue/256;return vec2(v0,packedIntValue-v0*256);}vec2 unpack_opacity(const uint packedOpacity) {return vec2(float(packedOpacity >> 1u)/127.0,float(packedOpacity & 1u));}vec4 decode_color(const vec2 encodedColor) {return vec4(unpack_float(encodedColor[0])/255.0,unpack_float(encodedColor[1])/255.0\n);}float unpack_mix_vec2(const vec2 packedValue,const float t) {return mix(packedValue[0],packedValue[1],t);}vec4 unpack_mix_color(const vec4 packedColors,const float t) {vec4 minColor=decode_color(vec2(packedColors[0],packedColors[1]));vec4 maxColor=decode_color(vec2(packedColors[2],packedColors[3]));return mix(minColor,maxColor,t);}vec2 get_pattern_pos(const vec2 pixel_coord_upper,const vec2 pixel_coord_lower,const vec2 pattern_size,const float tile_units_to_pixels,const vec2 pos) {vec2 offset=mod(mod(mod(pixel_coord_upper,pattern_size)*256.0,pattern_size)*256.0+pixel_coord_lower,pattern_size);return (tile_units_to_pixels*pos+offset)/pattern_size;}mat3 rotationMatrixFromAxisAngle(vec3 u,float angle) {float c=cos(angle);float s=sin(angle);float c2=1.0-c;return mat3(u.x*u.x*c2+ c,u.x*u.y*c2-u.z*s,u.x*u.z*c2+u.y*s,u.y*u.x*c2+u.z*s,u.y*u.y*c2+ c,u.y*u.z*c2-u.x*s,u.z*u.x*c2-u.y*s,u.z*u.y*c2+u.x*s,u.z*u.z*c2+ c\n);}\n#ifdef TERRAIN3D\nuniform sampler2D u_terrain;uniform float u_terrain_dim;uniform mat4 u_terrain_matrix;uniform vec4 u_terrain_unpack;uniform float u_terrain_exaggeration;uniform highp sampler2D u_depth;\n#endif\nconst highp vec4 bitSh=vec4(256.*256.*256.,256.*256.,256.,1.);const highp vec4 bitShifts=vec4(1.)/bitSh;highp float unpack(highp vec4 color) {return dot(color,bitShifts);}highp float depthOpacity(vec3 frag) {\n#ifdef TERRAIN3D\nhighp float d=unpack(texture(u_depth,frag.xy*0.5+0.5))+0.0001-frag.z;return 1.0-max(0.0,min(1.0,-d*500.0));\n#else\nreturn 1.0;\n#endif\n}float calculate_visibility(vec4 pos) {\n#ifdef TERRAIN3D\nvec3 frag=pos.xyz/pos.w;highp float d=depthOpacity(frag);if (d > 0.95) return 1.0;return (d+depthOpacity(frag+vec3(0.0,0.01,0.0)))/2.0;\n#else\nreturn 1.0;\n#endif\n}float ele(ivec2 pos) {\n#ifdef TERRAIN3D\nvec4 rgb=(texelFetch(u_terrain,pos,0)*255.0)*u_terrain_unpack;return rgb.r+rgb.g+rgb.b-u_terrain_unpack.a;\n#else\nreturn 0.0;\n#endif\n}float get_elevation(vec2 pos) {\n#ifdef TERRAIN3D\n#ifdef GLOBE\nif ((pos.y <-32767.5) || (pos.y > 32766.5)) {return 0.0;}\n#endif\nvec2 coord=(u_terrain_matrix*vec4(pos,0.0,1.0)).xy*u_terrain_dim+1.0;vec2 f=fract(coord);ivec2 c=ivec2(floor(coord));ivec2 hi=textureSize(u_terrain,0)-1;float tl=ele(clamp(c,ivec2(0),hi));float tr=ele(clamp(c+ivec2(1,0),ivec2(0),hi));float bl=ele(clamp(c+ivec2(0,1),ivec2(0),hi));float br=ele(clamp(c+ivec2(1,1),ivec2(0),hi));float elevation=mix(mix(tl,tr,f.x),mix(bl,br,f.x),f.y);return elevation*u_terrain_exaggeration;\n#else\nreturn 0.0;\n#endif\n}const float PI=3.141592653589793;uniform mat4 u_projection_matrix;";
|
|
8427
8555
|
//#endregion
|
|
8428
8556
|
//#region src/shaders/glsl/background.fragment.glsl.g.ts
|
|
8429
8557
|
var background_fragment_glsl_g_default = "uniform vec4 u_color;uniform float u_opacity;void main() {fragColor=u_color*u_opacity;\n#ifdef OVERDRAW_INSPECTOR\nfragColor=vec4(1.0);\n#endif\n}";
|
|
@@ -8459,7 +8587,7 @@ const shaders = {
|
|
|
8459
8587
|
heatmapTexture: prepare("uniform sampler2D u_image;uniform sampler2D u_color_ramp;uniform float u_opacity;in vec2 v_pos;void main() {float t=texture(u_image,v_pos).r;vec4 color=texture(u_color_ramp,vec2(t,0.5));fragColor=color*u_opacity;\n#ifdef OVERDRAW_INSPECTOR\nfragColor=vec4(0.0);\n#endif\n}", "uniform mat4 u_matrix;uniform vec2 u_world;layout(location=0) in vec2 a_pos;out vec2 v_pos;void main() {gl_Position=u_matrix*vec4(a_pos*u_world,0,1);v_pos.x=a_pos.x;v_pos.y=1.0-a_pos.y;}"),
|
|
8460
8588
|
collisionBox: prepare("flat in float v_placed;flat in float v_notUsed;void main() {float alpha=0.5;fragColor=vec4(1.0,0.0,0.0,1.0)*alpha;if (v_placed > 0.5) {fragColor=vec4(0.0,0.0,1.0,0.5)*alpha;}if (v_notUsed > 0.5) {fragColor*=.1;}}", "layout(location=0) in vec2 a_anchor_pos;layout(location=1) in vec2 a_placed;layout(location=2) in vec2 a_box_real;uniform vec2 u_pixel_extrude_scale;flat out float v_placed;flat out float v_notUsed;void main() {gl_Position=projectTileWithElevation(a_anchor_pos,get_elevation(a_anchor_pos));gl_Position.xy=((a_box_real+0.5)*u_pixel_extrude_scale*2.0-1.0)*vec2(1.0,-1.0)*gl_Position.w;if (gl_Position.z/gl_Position.w < 1.1) {gl_Position.z=0.5;}v_placed=a_placed.x;v_notUsed=a_placed.y;}"),
|
|
8461
8589
|
collisionCircle: prepare("flat in float v_radius;in vec2 v_extrude;flat in float v_collision;void main() {float alpha=0.5;float stroke_radius=0.9;float distance_to_center=length(v_extrude);float distance_to_edge=abs(distance_to_center-v_radius);float opacity_t=smoothstep(-stroke_radius,0.0,-distance_to_edge);vec4 color=mix(vec4(0.0,0.0,1.0,0.5),vec4(1.0,0.0,0.0,1.0),v_collision);fragColor=color*alpha*opacity_t;}", "layout(location=0) in vec2 a_pos;layout(location=1) in float a_radius;layout(location=2) in vec2 a_flags;uniform vec2 u_viewport_size;flat out float v_radius;out vec2 v_extrude;flat out float v_collision;void main() {float radius=a_radius;float collision=a_flags.x;float vertexIdx=a_flags.y;vec2 quadVertexOffset=vec2(mix(-1.0,1.0,float(vertexIdx >=2.0)),mix(-1.0,1.0,float(vertexIdx >=1.0 && vertexIdx <=2.0)));vec2 quadVertexExtent=quadVertexOffset*radius;float padding_factor=1.2;v_radius=radius;v_extrude=quadVertexExtent*padding_factor;v_collision=collision;gl_Position=vec4((a_pos/u_viewport_size*2.0-1.0)*vec2(1.0,-1.0),0.0,1.0)+vec4(quadVertexExtent*padding_factor/u_viewport_size*2.0,0.0,0.0);}"),
|
|
8462
|
-
colorRelief: prepare("#ifdef GL_ES\nprecision highp float;\n#endif\nuniform sampler2D u_image;uniform vec4 u_unpack;uniform sampler2D u_elevation_stops;uniform sampler2D u_color_stops;uniform int u_color_ramp_size;uniform float u_opacity;in vec2 v_pos;float getElevation(vec2 coord) {vec4 data=texture(u_image,coord)*255.0;data.a=-1.0;return dot(data,u_unpack);}float getElevationStop(int stop) {
|
|
8590
|
+
colorRelief: prepare("#ifdef GL_ES\nprecision highp float;\n#endif\nuniform sampler2D u_image;uniform vec4 u_unpack;uniform sampler2D u_elevation_stops;uniform sampler2D u_color_stops;uniform int u_color_ramp_size;uniform float u_opacity;in vec2 v_pos;float getElevation(vec2 coord) {vec4 data=texture(u_image,coord)*255.0;data.a=-1.0;return dot(data,u_unpack);}float getElevationStop(int stop) {vec4 data=texelFetch(u_elevation_stops,ivec2(stop,0),0)*255.0;data.a=-1.0;return dot(data,u_unpack);}void main() {float el=getElevation(v_pos);int r=(u_color_ramp_size-1);int l=0;float el_l=getElevationStop(l);float el_r=getElevationStop(r);while(r-l > 1){int m=(r+l)/2;float el_m=getElevationStop(m);if(el < el_m){r=m;el_r=el_m;}else\n{l=m;el_l=el_m;}}float x=(float(l)+(el-el_l)/(el_r-el_l)+0.5)/float(u_color_ramp_size);fragColor=u_opacity*texture(u_color_stops,vec2(x,0));\n#ifdef OVERDRAW_INSPECTOR\nfragColor=vec4(1.0);\n#endif\n}", "uniform vec2 u_dimension;layout(location=0) in vec2 a_pos;out vec2 v_pos;void main() {gl_Position=projectTile(a_pos,a_pos);highp vec2 epsilon=1.0/u_dimension;float scale=(u_dimension.x-2.0)/u_dimension.x;v_pos=(a_pos/8192.0)*scale+epsilon;if (a_pos.y <-32767.5) {v_pos.y=0.0;}if (a_pos.y > 32766.5) {v_pos.y=1.0;}}"),
|
|
8463
8591
|
debug: prepare("uniform highp vec4 u_color;uniform sampler2D u_overlay;in vec2 v_uv;void main() {vec4 overlay_color=texture(u_overlay,v_uv);fragColor=mix(u_color,overlay_color,overlay_color.a);}", "layout(location=0) in vec2 a_pos;out vec2 v_uv;uniform float u_overlay_scale;void main() {v_uv=a_pos/8192.0;gl_Position=projectTileWithElevation(a_pos*u_overlay_scale,get_elevation(a_pos));}"),
|
|
8464
8592
|
depth: prepare(clipping_mask_fragment_glsl_g_default, "layout(location=0) in vec2 a_pos;void main() {\n#ifdef GLOBE\ngl_Position=projectTileFor3D(a_pos,0.0);\n#else\ngl_Position=u_projection_matrix*vec4(a_pos,0.0,1.0);\n#endif\n}"),
|
|
8465
8593
|
fill: prepare("#pragma maplibre: define highp vec4 color\n#pragma maplibre: define lowp float opacity\nvoid main() {\n#pragma maplibre: initialize highp vec4 color\n#pragma maplibre: initialize lowp float opacity\nfragColor=color*opacity;\n#ifdef OVERDRAW_INSPECTOR\nfragColor=vec4(1.0);\n#endif\n}", "uniform vec2 u_fill_translate;layout(location=0) in vec2 a_pos;\n#pragma maplibre: define highp vec4 color\n#pragma maplibre: define lowp float opacity\nvoid main() {\n#pragma maplibre: initialize highp vec4 color\n#pragma maplibre: initialize lowp float opacity\nif (opacity < 0.01) {gl_Position=vec4(-2.0,-2.0,-2.0,1.0);return;}gl_Position=projectTile(a_pos+u_fill_translate,a_pos);}"),
|
|
@@ -8468,7 +8596,7 @@ const shaders = {
|
|
|
8468
8596
|
fillPattern: prepare("#ifdef GL_ES\nprecision highp float;\n#endif\nuniform vec2 u_texsize;uniform float u_fade;uniform sampler2D u_image;in vec2 v_pos_a;in vec2 v_pos_b;\n#pragma maplibre: define lowp float opacity\n#pragma maplibre: define lowp vec4 pattern_from\n#pragma maplibre: define lowp vec4 pattern_to\nvoid main() {\n#pragma maplibre: initialize lowp float opacity\n#pragma maplibre: initialize mediump vec4 pattern_from\n#pragma maplibre: initialize mediump vec4 pattern_to\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;vec2 imagecoord=mod(v_pos_a,1.0);vec2 pos=mix(pattern_tl_a/u_texsize,pattern_br_a/u_texsize,imagecoord);vec4 color1=texture(u_image,pos);vec2 imagecoord_b=mod(v_pos_b,1.0);vec2 pos2=mix(pattern_tl_b/u_texsize,pattern_br_b/u_texsize,imagecoord_b);vec4 color2=texture(u_image,pos2);fragColor=mix(color1,color2,u_fade)*opacity;\n#ifdef OVERDRAW_INSPECTOR\nfragColor=vec4(1.0);\n#endif\n}", "uniform vec2 u_pixel_coord_upper;uniform vec2 u_pixel_coord_lower;uniform vec3 u_scale;uniform vec2 u_fill_translate;layout(location=0) in vec2 a_pos;out vec2 v_pos_a;out vec2 v_pos_b;\n#pragma maplibre: define lowp float opacity\n#pragma maplibre: define lowp vec4 pattern_from\n#pragma maplibre: define lowp vec4 pattern_to\n#pragma maplibre: define lowp float pixel_ratio_from\n#pragma maplibre: define lowp float pixel_ratio_to\nvoid main() {\n#pragma maplibre: initialize lowp float opacity\n#pragma maplibre: initialize mediump vec4 pattern_from\n#pragma maplibre: initialize mediump vec4 pattern_to\n#pragma maplibre: initialize lowp float pixel_ratio_from\n#pragma maplibre: initialize lowp float pixel_ratio_to\nif (opacity < 0.01) {gl_Position=vec4(-2.0,-2.0,-2.0,1.0);return;}vec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;float tileZoomRatio=u_scale.x;float fromScale=u_scale.y;float toScale=u_scale.z;vec2 display_size_a=(pattern_br_a-pattern_tl_a)/pixel_ratio_from;vec2 display_size_b=(pattern_br_b-pattern_tl_b)/pixel_ratio_to;gl_Position=projectTile(a_pos+u_fill_translate,a_pos);v_pos_a=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,fromScale*display_size_a,tileZoomRatio,a_pos);v_pos_b=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,toScale*display_size_b,tileZoomRatio,a_pos);}"),
|
|
8469
8597
|
fillExtrusion: prepare("in vec4 v_color;void main() {fragColor=v_color;\n#ifdef OVERDRAW_INSPECTOR\nfragColor=vec4(1.0);\n#endif\n}", "uniform vec3 u_lightcolor;uniform lowp vec3 u_lightpos;uniform lowp vec3 u_lightpos_globe;uniform lowp float u_lightintensity;uniform float u_vertical_gradient;uniform lowp float u_opacity;uniform vec2 u_fill_translate;layout(location=0) in vec2 a_pos;layout(location=1) in ivec4 a_normal_ed;\n#ifdef TERRAIN3D\nlayout(location=2) in vec2 a_centroid;\n#endif\nout vec4 v_color;\n#pragma maplibre: define highp float base\n#pragma maplibre: define highp float height\n#pragma maplibre: define highp vec4 color\nvoid main() {\n#pragma maplibre: initialize highp float base\n#pragma maplibre: initialize highp float height\n#pragma maplibre: initialize highp vec4 color\nvec3 normal=vec3(a_normal_ed.xyz);\n#ifdef TERRAIN3D\nfloat height_terrain3d_offset=get_elevation(a_centroid);float base_terrain3d_offset=height_terrain3d_offset-(base > 0.0 ? 0.0 : 10.0);\n#else\nfloat height_terrain3d_offset=0.0;float base_terrain3d_offset=0.0;\n#endif\nbase=max(0.0,base)+base_terrain3d_offset;height=max(0.0,height)+height_terrain3d_offset;float t=float(a_normal_ed.x & 1);float elevation=t > 0.0 ? height : base;vec2 posInTile=a_pos+u_fill_translate;\n#ifdef GLOBE\nvec3 spherePos=projectToSphere(posInTile,a_pos);gl_Position=interpolateProjectionFor3D(posInTile,spherePos,elevation);\n#else\ngl_Position=u_projection_matrix*vec4(posInTile,elevation,1.0);\n#endif\nfloat colorvalue=color.r*0.2126+color.g*0.7152+color.b*0.0722;v_color=vec4(0.0,0.0,0.0,1.0);vec4 ambientlight=vec4(0.03,0.03,0.03,1.0);color+=ambientlight;vec3 normalForLighting=normal/16384.0;float directional=clamp(dot(normalForLighting,u_lightpos),0.0,1.0);\n#ifdef GLOBE\nmat3 rotMatrix=globeGetRotationMatrix(spherePos);normalForLighting=rotMatrix*normalForLighting;directional=mix(directional,clamp(dot(normalForLighting,u_lightpos_globe),0.0,1.0),u_projection_transition);\n#endif\ndirectional=mix((1.0-u_lightintensity),max((1.0-colorvalue+u_lightintensity),1.0),directional);if (normal.y !=0.0) {directional*=((1.0-u_vertical_gradient)+(u_vertical_gradient*clamp((t+base)*pow(height/150.0,0.5),mix(0.7,0.98,1.0-u_lightintensity),1.0)));}v_color.r+=clamp(color.r*directional*u_lightcolor.r,mix(0.0,0.3,1.0-u_lightcolor.r),1.0);v_color.g+=clamp(color.g*directional*u_lightcolor.g,mix(0.0,0.3,1.0-u_lightcolor.g),1.0);v_color.b+=clamp(color.b*directional*u_lightcolor.b,mix(0.0,0.3,1.0-u_lightcolor.b),1.0);v_color*=u_opacity;}"),
|
|
8470
8598
|
fillExtrusionPattern: prepare("uniform vec2 u_texsize;uniform float u_fade;uniform sampler2D u_image;in vec2 v_pos_a;in vec2 v_pos_b;in vec4 v_lighting;\n#pragma maplibre: define lowp float base\n#pragma maplibre: define lowp float height\n#pragma maplibre: define lowp vec4 pattern_from\n#pragma maplibre: define lowp vec4 pattern_to\n#pragma maplibre: define lowp float pixel_ratio_from\n#pragma maplibre: define lowp float pixel_ratio_to\nvoid main() {\n#pragma maplibre: initialize lowp float base\n#pragma maplibre: initialize lowp float height\n#pragma maplibre: initialize mediump vec4 pattern_from\n#pragma maplibre: initialize mediump vec4 pattern_to\n#pragma maplibre: initialize lowp float pixel_ratio_from\n#pragma maplibre: initialize lowp float pixel_ratio_to\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;vec2 imagecoord=mod(v_pos_a,1.0);vec2 pos=mix(pattern_tl_a/u_texsize,pattern_br_a/u_texsize,imagecoord);vec4 color1=texture(u_image,pos);vec2 imagecoord_b=mod(v_pos_b,1.0);vec2 pos2=mix(pattern_tl_b/u_texsize,pattern_br_b/u_texsize,imagecoord_b);vec4 color2=texture(u_image,pos2);vec4 mixedColor=mix(color1,color2,u_fade);fragColor=mixedColor*v_lighting;\n#ifdef OVERDRAW_INSPECTOR\nfragColor=vec4(1.0);\n#endif\n}", "uniform vec2 u_pixel_coord_upper;uniform vec2 u_pixel_coord_lower;uniform float u_height_factor;uniform vec3 u_scale;uniform float u_vertical_gradient;uniform lowp float u_opacity;uniform vec2 u_fill_translate;uniform vec3 u_lightcolor;uniform lowp vec3 u_lightpos;uniform lowp vec3 u_lightpos_globe;uniform lowp float u_lightintensity;layout(location=0) in vec2 a_pos;layout(location=1) in ivec4 a_normal_ed;\n#ifdef TERRAIN3D\nlayout(location=2) in vec2 a_centroid;\n#endif\n#ifdef GLOBE\nout vec3 v_sphere_pos;\n#endif\nout vec2 v_pos_a;out vec2 v_pos_b;out vec4 v_lighting;\n#pragma maplibre: define lowp float base\n#pragma maplibre: define lowp float height\n#pragma maplibre: define lowp vec4 pattern_from\n#pragma maplibre: define lowp vec4 pattern_to\n#pragma maplibre: define lowp float pixel_ratio_from\n#pragma maplibre: define lowp float pixel_ratio_to\nvoid main() {\n#pragma maplibre: initialize lowp float base\n#pragma maplibre: initialize lowp float height\n#pragma maplibre: initialize mediump vec4 pattern_from\n#pragma maplibre: initialize mediump vec4 pattern_to\n#pragma maplibre: initialize lowp float pixel_ratio_from\n#pragma maplibre: initialize lowp float pixel_ratio_to\nvec2 pattern_tl_a=pattern_from.xy;vec2 pattern_br_a=pattern_from.zw;vec2 pattern_tl_b=pattern_to.xy;vec2 pattern_br_b=pattern_to.zw;float tileRatio=u_scale.x;float fromScale=u_scale.y;float toScale=u_scale.z;vec3 normal=vec3(a_normal_ed.xyz);float edgedistance=float(a_normal_ed.w);vec2 display_size_a=(pattern_br_a-pattern_tl_a)/pixel_ratio_from;vec2 display_size_b=(pattern_br_b-pattern_tl_b)/pixel_ratio_to;\n#ifdef TERRAIN3D\nfloat height_terrain3d_offset=get_elevation(a_centroid);float base_terrain3d_offset=height_terrain3d_offset-(base > 0.0 ? 0.0 : 10.0);\n#else\nfloat height_terrain3d_offset=0.0;float base_terrain3d_offset=0.0;\n#endif\nbase=max(0.0,base)+base_terrain3d_offset;height=max(0.0,height)+height_terrain3d_offset;float t=float(a_normal_ed.x & 1);float elevation=t > 0.0 ? height : base;vec2 posInTile=a_pos+u_fill_translate;\n#ifdef GLOBE\nvec3 spherePos=projectToSphere(posInTile,a_pos);vec3 elevatedPos=spherePos*(1.0+elevation/GLOBE_RADIUS);v_sphere_pos=elevatedPos;gl_Position=interpolateProjectionFor3D(posInTile,spherePos,elevation);\n#else\ngl_Position=u_projection_matrix*vec4(posInTile,elevation,1.0);\n#endif\nvec2 pos=a_normal_ed.x==1 && a_normal_ed.y==0 && a_normal_ed.z==16384\n? a_pos\n: vec2(edgedistance,elevation*u_height_factor);v_pos_a=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,fromScale*display_size_a,tileRatio,pos);v_pos_b=get_pattern_pos(u_pixel_coord_upper,u_pixel_coord_lower,toScale*display_size_b,tileRatio,pos);v_lighting=vec4(0.0,0.0,0.0,1.0);float directional=clamp(dot(normal/16383.0,u_lightpos),0.0,1.0);directional=mix((1.0-u_lightintensity),max((0.5+u_lightintensity),1.0),directional);if (normal.y !=0.0) {directional*=((1.0-u_vertical_gradient)+(u_vertical_gradient*clamp((t+base)*pow(height/150.0,0.5),mix(0.7,0.98,1.0-u_lightintensity),1.0)));}v_lighting.rgb+=clamp(directional*u_lightcolor,mix(vec3(0.0),vec3(0.3),1.0-u_lightcolor),vec3(1.0));v_lighting*=u_opacity;}"),
|
|
8471
|
-
hillshadePrepare: prepare("#ifdef GL_ES\nprecision highp float;\n#endif\nuniform sampler2D u_image;in vec2 v_pos;uniform vec2 u_dimension;uniform float u_zoom;uniform vec4 u_unpack;float getElevation(
|
|
8599
|
+
hillshadePrepare: prepare("#ifdef GL_ES\nprecision highp float;\n#endif\nuniform sampler2D u_image;in vec2 v_pos;uniform vec2 u_dimension;uniform float u_zoom;uniform vec4 u_unpack;float getElevation(ivec2 texel) {vec4 data=texelFetch(u_image,texel,0)*255.0;data.a=-1.0;return dot(data,u_unpack);}void main() {ivec2 pos=ivec2(gl_FragCoord.xy)+ivec2(1);float tileSize=u_dimension.x-2.0;float a=getElevation(pos+ivec2(-1,-1));float b=getElevation(pos+ivec2(0,-1));float c=getElevation(pos+ivec2(1,-1));float d=getElevation(pos+ivec2(-1,0));float e=getElevation(pos);float f=getElevation(pos+ivec2(1,0));float g=getElevation(pos+ivec2(-1,1));float h=getElevation(pos+ivec2(0,1));float i=getElevation(pos+ivec2(1,1));float exaggerationFactor=u_zoom < 2.0 ? 0.4 : u_zoom < 4.5 ? 0.35 : 0.3;float exaggeration=u_zoom < 15.0 ? (u_zoom-15.0)*exaggerationFactor : 0.0;vec2 deriv=vec2((c+f+f+i)-(a+d+d+g),(g+h+h+i)-(a+b+b+c))*tileSize/pow(2.0,exaggeration+(28.2562-u_zoom));fragColor=clamp(vec4(deriv.x/8.0+0.5,deriv.y/8.0+0.5,1.0,1.0),0.0,1.0);\n#ifdef OVERDRAW_INSPECTOR\nfragColor=vec4(1.0);\n#endif\n}", "uniform mat4 u_matrix;uniform vec2 u_dimension;layout(location=0) in vec2 a_pos;layout(location=1) in vec2 a_texture_pos;out vec2 v_pos;void main() {gl_Position=u_matrix*vec4(a_pos,0,1);highp vec2 epsilon=1.0/u_dimension;float scale=(u_dimension.x-2.0)/u_dimension.x;v_pos=(a_texture_pos/8192.0)*scale+epsilon;}"),
|
|
8472
8600
|
hillshade: prepare("uniform sampler2D u_image;in vec2 v_pos;uniform vec2 u_latrange;uniform float u_exaggeration;uniform vec4 u_accent;uniform int u_method;uniform float u_altitudes[NUM_ILLUMINATION_SOURCES];uniform float u_azimuths[NUM_ILLUMINATION_SOURCES];uniform vec4 u_shadows[NUM_ILLUMINATION_SOURCES];uniform vec4 u_highlights[NUM_ILLUMINATION_SOURCES];\n#define PI 3.141592653589793\n#define STANDARD 0\n#define COMBINED 1\n#define IGOR 2\n#define MULTIDIRECTIONAL 3\n#define BASIC 4\nfloat get_aspect(vec2 deriv){return deriv.x !=0.0 ? atan(deriv.y,-deriv.x) : PI/2.0*(deriv.y > 0.0 ? 1.0 :-1.0);}void igor_hillshade(vec2 deriv){deriv=deriv*u_exaggeration*2.0;float aspect=get_aspect(deriv);float azimuth=u_azimuths[0]+PI;float slope_stength=atan(length(deriv))*2.0/PI;float aspect_strength=1.0-abs(mod((aspect+azimuth)/PI+0.5,2.0)-1.0);float shadow_strength=slope_stength*aspect_strength;float highlight_strength=slope_stength*(1.0-aspect_strength);fragColor=u_shadows[0]*shadow_strength+u_highlights[0]*highlight_strength;}void standard_hillshade(vec2 deriv){float azimuth=u_azimuths[0]+PI;float slope=atan(0.625*length(deriv));float aspect=get_aspect(deriv);float intensity=u_exaggeration;float base=1.875-intensity*1.75;float maxValue=0.5*PI;float scaledSlope=intensity !=0.5 ? ((pow(base,slope)-1.0)/(pow(base,maxValue)-1.0))*maxValue : slope;float accent=cos(scaledSlope);vec4 accent_color=(1.0-accent)*u_accent*clamp(intensity*2.0,0.0,1.0);float shade=abs(mod((aspect+azimuth)/PI+0.5,2.0)-1.0);vec4 shade_color=mix(u_shadows[0],u_highlights[0],shade)*sin(scaledSlope)*clamp(intensity*2.0,0.0,1.0);fragColor=accent_color*(1.0-shade_color.a)+shade_color;}void basic_hillshade(vec2 deriv){deriv=deriv*u_exaggeration*2.0;float azimuth=u_azimuths[0]+PI;float cos_az=cos(azimuth);float sin_az=sin(azimuth);float cos_alt=cos(u_altitudes[0]);float sin_alt=sin(u_altitudes[0]);float cang=(sin_alt-(deriv.y*cos_az*cos_alt-deriv.x*sin_az*cos_alt))/sqrt(1.0+dot(deriv,deriv));float shade=clamp(cang,0.0,1.0);if(shade > 0.5){fragColor=u_highlights[0]*(2.0*shade-1.0);}else\n{fragColor=u_shadows[0]*(1.0-2.0*shade);}}void multidirectional_hillshade(vec2 deriv){deriv=deriv*u_exaggeration*2.0;fragColor=vec4(0,0,0,0);for(int i=0; i < NUM_ILLUMINATION_SOURCES; i++){float cos_alt=cos(u_altitudes[i]);float sin_alt=sin(u_altitudes[i]);float cos_az=-cos(u_azimuths[i]);float sin_az=-sin(u_azimuths[i]);float cang=(sin_alt-(deriv.y*cos_az*cos_alt-deriv.x*sin_az*cos_alt))/sqrt(1.0+dot(deriv,deriv));float shade=clamp(cang,0.0,1.0);if(shade > 0.5){fragColor+=u_highlights[i]*(2.0*shade-1.0)/float(NUM_ILLUMINATION_SOURCES);}else\n{fragColor+=u_shadows[i]*(1.0-2.0*shade)/float(NUM_ILLUMINATION_SOURCES);}}}void combined_hillshade(vec2 deriv){deriv=deriv*u_exaggeration*2.0;float azimuth=u_azimuths[0]+PI;float cos_az=cos(azimuth);float sin_az=sin(azimuth);float cos_alt=cos(u_altitudes[0]);float sin_alt=sin(u_altitudes[0]);float cang=acos((sin_alt-(deriv.y*cos_az*cos_alt-deriv.x*sin_az*cos_alt))/sqrt(1.0+dot(deriv,deriv)));cang=clamp(cang,0.0,PI/2.0);float shade=cang*atan(length(deriv))*4.0/PI/PI;float highlight=(PI/2.0-cang)*atan(length(deriv))*4.0/PI/PI;fragColor=u_shadows[0]*shade+u_highlights[0]*highlight;}void main() {vec4 pixel=texture(u_image,v_pos);float scaleFactor=cos(radians((u_latrange[0]-u_latrange[1])*(1.0-v_pos.y)+u_latrange[1]));vec2 deriv=((pixel.rg*8.0)-4.0)/scaleFactor;if (u_method==BASIC) {basic_hillshade(deriv);} else if (u_method==COMBINED) {combined_hillshade(deriv);} else if (u_method==IGOR) {igor_hillshade(deriv);} else if (u_method==MULTIDIRECTIONAL) {multidirectional_hillshade(deriv);} else if (u_method==STANDARD) {standard_hillshade(deriv);} else {standard_hillshade(deriv);}\n#ifdef OVERDRAW_INSPECTOR\nfragColor=vec4(1.0);\n#endif\n}", "uniform mat4 u_matrix;layout(location=0) in vec2 a_pos;out vec2 v_pos;void main() {gl_Position=projectTile(a_pos,a_pos);v_pos=a_pos/8192.0;if (a_pos.y <-32767.5) {v_pos.y=0.0;}if (a_pos.y > 32766.5) {v_pos.y=1.0;}}"),
|
|
8473
8601
|
line: prepare("uniform lowp float u_device_pixel_ratio;flat in vec2 v_width2;in vec2 v_normal;in float v_gamma_scale;\n#ifdef GLOBE\nin float v_depth;\n#endif\n#pragma maplibre: define highp vec4 color\n#pragma maplibre: define lowp float blur\n#pragma maplibre: define lowp float opacity\nvoid main() {\n#pragma maplibre: initialize highp vec4 color\n#pragma maplibre: initialize lowp float blur\n#pragma maplibre: initialize lowp float opacity\nclipAntimeridian();float dist=length(v_normal)*v_width2.s;float blur2=(blur+1.0/u_device_pixel_ratio)*v_gamma_scale;float alpha=clamp(min(dist-(v_width2.t-blur2),v_width2.s-dist)/blur2,0.0,1.0);fragColor=color*(alpha*opacity);\n#ifdef GLOBE\nif (v_depth > 1.0) {discard;}\n#endif\n#ifdef OVERDRAW_INSPECTOR\nfragColor=vec4(1.0);\n#endif\n}", "\n#define scale 0.015873016\nlayout(location=0) in ivec2 a_pos_normal;layout(location=1) in uvec4 a_data;uniform vec2 u_translation;uniform mediump float u_ratio;uniform vec2 u_units_to_pixels;uniform lowp float u_device_pixel_ratio;out vec2 v_normal;flat out vec2 v_width2;out float v_gamma_scale;out highp float v_linesofar;\n#ifdef GLOBE\nout float v_depth;\n#endif\n#pragma maplibre: define highp vec4 color\n#pragma maplibre: define lowp float blur\n#pragma maplibre: define lowp float opacity\n#pragma maplibre: define mediump float gapwidth\n#pragma maplibre: define lowp float offset\n#pragma maplibre: define mediump float width\nvoid main() {\n#pragma maplibre: initialize highp vec4 color\n#pragma maplibre: initialize lowp float blur\n#pragma maplibre: initialize lowp float opacity\n#pragma maplibre: initialize mediump float gapwidth\n#pragma maplibre: initialize lowp float offset\n#pragma maplibre: initialize mediump float width\nif (opacity < 0.01) {gl_Position=vec4(-2.0,-2.0,-2.0,1.0);return;}float ANTIALIASING=1.0/u_device_pixel_ratio/2.0;vec2 a_extrude=vec2(ivec2(a_data.xy)-128);float a_direction=float(int(a_data.z & 3u)-1);v_linesofar=float((a_data.z >> 2u)+a_data.w*64u)*2.0;vec2 pos=vec2(a_pos_normal >> 1);mediump vec2 normal=vec2(a_pos_normal & 1);normal.y=normal.y*2.0-1.0;v_normal=normal;gapwidth=gapwidth/2.0;float halfwidth=width/2.0;offset=-1.0*offset;float inset=gapwidth+(gapwidth > 0.0 ? ANTIALIASING : 0.0);float outset=gapwidth+halfwidth*(gapwidth > 0.0 ? 2.0 : 1.0)+(halfwidth==0.0 ? 0.0 : ANTIALIASING);mediump vec2 dist=outset*a_extrude*scale;mediump float u=0.5*a_direction;mediump float t=1.0-abs(u);mediump vec2 offset2=offset*a_extrude*scale*normal.y*mat2(t,-u,u,t);float adjustedThickness=projectLineThickness(pos.y);vec4 projected_no_extrude=projectTile(pos+offset2/u_ratio*adjustedThickness+u_translation);vec4 projected_with_extrude=projectTile(pos+offset2/u_ratio*adjustedThickness+u_translation+dist/u_ratio*adjustedThickness);gl_Position=projected_with_extrude;\n#ifdef GLOBE\nv_depth=gl_Position.z/gl_Position.w;\n#endif\n#ifdef TERRAIN3D\nv_gamma_scale=1.0;\n#else\nfloat extrude_length_without_perspective=length(dist);float extrude_length_with_perspective=length((projected_with_extrude.xy-projected_no_extrude.xy)/projected_with_extrude.w*u_units_to_pixels);v_gamma_scale=extrude_length_without_perspective/extrude_length_with_perspective;\n#endif\nv_width2=vec2(outset,inset);}"),
|
|
8474
8602
|
lineGradient: prepare("uniform lowp float u_device_pixel_ratio;uniform sampler2D u_image;flat in vec2 v_width2;in vec2 v_normal;in float v_gamma_scale;in highp vec2 v_uv;\n#ifdef GLOBE\nin float v_depth;\n#endif\n#pragma maplibre: define lowp float blur\n#pragma maplibre: define lowp float opacity\nvoid main() {\n#pragma maplibre: initialize lowp float blur\n#pragma maplibre: initialize lowp float opacity\nclipAntimeridian();float dist=length(v_normal)*v_width2.s;float blur2=(blur+1.0/u_device_pixel_ratio)*v_gamma_scale;float alpha=clamp(min(dist-(v_width2.t-blur2),v_width2.s-dist)/blur2,0.0,1.0);vec4 color=texture(u_image,v_uv);fragColor=color*(alpha*opacity);\n#ifdef GLOBE\nif (v_depth > 1.0) {discard;}\n#endif\n#ifdef OVERDRAW_INSPECTOR\nfragColor=vec4(1.0);\n#endif\n}", "\n#define scale 0.015873016\nlayout(location=0) in ivec2 a_pos_normal;layout(location=1) in uvec4 a_data;layout(location=2) in float a_uv_x;layout(location=3) in float a_split_index;uniform vec2 u_translation;uniform mediump float u_ratio;uniform lowp float u_device_pixel_ratio;uniform vec2 u_units_to_pixels;uniform float u_image_height;out vec2 v_normal;flat out vec2 v_width2;out float v_gamma_scale;out highp vec2 v_uv;\n#ifdef GLOBE\nout float v_depth;\n#endif\n#pragma maplibre: define lowp float blur\n#pragma maplibre: define lowp float opacity\n#pragma maplibre: define mediump float gapwidth\n#pragma maplibre: define lowp float offset\n#pragma maplibre: define mediump float width\nvoid main() {\n#pragma maplibre: initialize lowp float blur\n#pragma maplibre: initialize lowp float opacity\n#pragma maplibre: initialize mediump float gapwidth\n#pragma maplibre: initialize lowp float offset\n#pragma maplibre: initialize mediump float width\nif (opacity < 0.01) {gl_Position=vec4(-2.0,-2.0,-2.0,1.0);return;}float ANTIALIASING=1.0/u_device_pixel_ratio/2.0;vec2 a_extrude=vec2(ivec2(a_data.xy)-128);float a_direction=float(int(a_data.z & 3u)-1);highp float texel_height=1.0/u_image_height;highp float half_texel_height=0.5*texel_height;v_uv=vec2(a_uv_x,a_split_index*texel_height-half_texel_height);vec2 pos=vec2(a_pos_normal >> 1);mediump vec2 normal=vec2(a_pos_normal & 1);normal.y=normal.y*2.0-1.0;v_normal=normal;gapwidth=gapwidth/2.0;float halfwidth=width/2.0;offset=-1.0*offset;float inset=gapwidth+(gapwidth > 0.0 ? ANTIALIASING : 0.0);float outset=gapwidth+halfwidth*(gapwidth > 0.0 ? 2.0 : 1.0)+(halfwidth==0.0 ? 0.0 : ANTIALIASING);mediump vec2 dist=outset*a_extrude*scale;mediump float u=0.5*a_direction;mediump float t=1.0-abs(u);mediump vec2 offset2=offset*a_extrude*scale*normal.y*mat2(t,-u,u,t);float adjustedThickness=projectLineThickness(pos.y);vec4 projected_no_extrude=projectTile(pos+offset2/u_ratio*adjustedThickness+u_translation);vec4 projected_with_extrude=projectTile(pos+offset2/u_ratio*adjustedThickness+u_translation+dist/u_ratio*adjustedThickness);gl_Position=projected_with_extrude;\n#ifdef GLOBE\nv_depth=gl_Position.z/gl_Position.w;\n#endif\n#ifdef TERRAIN3D\nv_gamma_scale=1.0;\n#else\nfloat extrude_length_without_perspective=length(dist);float extrude_length_with_perspective=length((projected_with_extrude.xy-projected_no_extrude.xy)/projected_with_extrude.w*u_units_to_pixels);v_gamma_scale=extrude_length_without_perspective/extrude_length_with_perspective;\n#endif\nv_width2=vec2(outset,inset);}"),
|
|
@@ -10816,6 +10944,145 @@ function sphereSurfacePointToCoordinates(surface) {
|
|
|
10816
10944
|
} else return new LngLat(0, latDegrees);
|
|
10817
10945
|
}
|
|
10818
10946
|
/**
|
|
10947
|
+
* Returns the globe orientation quaternion for the given map center and bearing.
|
|
10948
|
+
* The inverse of {@link lngLatBearingFromOrientation}.
|
|
10949
|
+
*/
|
|
10950
|
+
function orientationFromLngLatBearing(lngLat, bearing) {
|
|
10951
|
+
return fromEuler(createVec4f64(), -lngLat.lng, -lngLat.lat, bearing);
|
|
10952
|
+
}
|
|
10953
|
+
/**
|
|
10954
|
+
* Given a globe orientation quaternion, returns the corresponding map center and bearing.
|
|
10955
|
+
* The inverse of {@link orientationFromLngLatBearing}.
|
|
10956
|
+
*/
|
|
10957
|
+
function lngLatBearingFromOrientation(q) {
|
|
10958
|
+
const x = q[0], y = q[1], z = q[2], w = q[3];
|
|
10959
|
+
return {
|
|
10960
|
+
lng: -Math.atan2(2 * (w * x + y * z), 1 - 2 * (x * x + y * y)) * 180 / Math.PI,
|
|
10961
|
+
lat: -Math.asin(clamp(2 * (w * y - z * x), -1, 1)) * 180 / Math.PI,
|
|
10962
|
+
bearing: Math.atan2(2 * (w * z + x * y), 1 - 2 * (y * y + z * z)) * 180 / Math.PI
|
|
10963
|
+
};
|
|
10964
|
+
}
|
|
10965
|
+
/** Kept just below a half turn so the center cannot land exactly on the far side of the globe. */
|
|
10966
|
+
const PAN_MAX_ANGLE = Math.PI * .98;
|
|
10967
|
+
/**
|
|
10968
|
+
* Returns the point on the globe that a drag towards `point` should aim at.
|
|
10969
|
+
*
|
|
10970
|
+
* Exact tracking breaks down at the silhouette: the ray meets the globe at `asin(D sin a) - a`,
|
|
10971
|
+
* whose slope runs away to infinity as the ray goes tangent, and past it there is no intersection
|
|
10972
|
+
* at all. So the exact curve is left {@link PAN_FALLOFF_BAND} early and continued with a hyperbola
|
|
10973
|
+
* matching it in value and slope, easing off and saturating short of the far side. Bell's virtual
|
|
10974
|
+
* trackball takes the same idea of easing a sphere into a hyperbola before the rim, though it fits
|
|
10975
|
+
* the curve differently: SGI's `trackball.c`, described in Henriksen, Sporring and Hornbæk,
|
|
10976
|
+
* "Virtual Trackballs Revisited", IEEE TVCG 10(2):206-216, 2004.
|
|
10977
|
+
*
|
|
10978
|
+
* The angle comes from atan2, so a ray pointing away from the globe is a wide angle the falloff
|
|
10979
|
+
* saturates rather than a case to reject.
|
|
10980
|
+
* @param tr - The transform being dragged.
|
|
10981
|
+
* @param point - The cursor position.
|
|
10982
|
+
*/
|
|
10983
|
+
function panSurfaceLocation(tr, point) {
|
|
10984
|
+
const origin = tr.cameraPosition;
|
|
10985
|
+
const distance = length$1(origin);
|
|
10986
|
+
if (distance <= 1) return tr.screenPointToLocation(point);
|
|
10987
|
+
const u = createVec3f64();
|
|
10988
|
+
normalize(u, origin);
|
|
10989
|
+
const direction = tr.getRayDirectionFromPixel(point);
|
|
10990
|
+
const c = -dot(direction, u);
|
|
10991
|
+
const lateral = createVec3f64();
|
|
10992
|
+
scaleAndAdd(lateral, direction, u, c);
|
|
10993
|
+
const s = length$1(lateral);
|
|
10994
|
+
if (s < 1e-9) return tr.screenPointToLocation(point);
|
|
10995
|
+
const angle = Math.atan2(s, c);
|
|
10996
|
+
const handoverAngle = Math.asin(1 / distance) * .9;
|
|
10997
|
+
if (angle < handoverAngle) return tr.screenPointToLocation(point);
|
|
10998
|
+
const sinHandover = distance * Math.sin(handoverAngle);
|
|
10999
|
+
const targetAtHandover = Math.asin(clamp(sinHandover, -1, 1)) - handoverAngle;
|
|
11000
|
+
const slopeAtHandover = distance * Math.cos(handoverAngle) / Math.sqrt(Math.max(1 - sinHandover * sinHandover, 1e-12)) - 1;
|
|
11001
|
+
const room = PAN_MAX_ANGLE - targetAtHandover;
|
|
11002
|
+
const excess = angle - handoverAngle;
|
|
11003
|
+
const target = targetAtHandover + room * (slopeAtHandover * excess) / (room + slopeAtHandover * excess);
|
|
11004
|
+
const e = createVec3f64();
|
|
11005
|
+
scale$2(e, lateral, 1 / s);
|
|
11006
|
+
const surface = createVec3f64();
|
|
11007
|
+
scale$2(surface, u, Math.cos(clamp(target, 0, PAN_MAX_ANGLE)));
|
|
11008
|
+
scaleAndAdd(surface, surface, e, Math.sin(clamp(target, 0, PAN_MAX_ANGLE)));
|
|
11009
|
+
normalize(surface, surface);
|
|
11010
|
+
return sphereSurfacePointToCoordinates(surface);
|
|
11011
|
+
}
|
|
11012
|
+
/**
|
|
11013
|
+
* Rotates the globe so that the given location appears at the given screen point, by composing
|
|
11014
|
+
* versors, the unit quaternions that represent rotations. Unlike the bearing-preserving
|
|
11015
|
+
* {@link ITransform.setLocationAtPoint}, this stays smooth near and across the poles, and keeps
|
|
11016
|
+
* panning once the cursor leaves the globe.
|
|
11017
|
+
*
|
|
11018
|
+
* Note: the delta rotation's axis is in the surface-vector frame of
|
|
11019
|
+
* {@link angularCoordinatesToSurfaceVector}, while the orientation quaternion uses the Euler frame
|
|
11020
|
+
* of {@link orientationFromLngLatBearing}, hence the component swizzle where they combine. Zoom is
|
|
11021
|
+
* adjusted to keep the planet the same size, as `setLocationAtPoint` does.
|
|
11022
|
+
* @param tr - The transform to rotate.
|
|
11023
|
+
* @param lnglat - The location to bring under `point`.
|
|
11024
|
+
* @param point - The screen point that `lnglat` should appear at.
|
|
11025
|
+
* @param panDelta - The drag's pixel delta. Used to re-derive the previous cursor location through
|
|
11026
|
+
* {@link panSurfaceLocation}, since both ends of the rotation must come from the same mapping.
|
|
11027
|
+
* @param fixedBearing - Applies the swing only, keeping the bearing fixed, which is what dragging
|
|
11028
|
+
* the globe does. Pass `false` to apply the twist about the view axis as well, so that the grabbed
|
|
11029
|
+
* location tracks the cursor exactly and the bearing drifts with it.
|
|
11030
|
+
*/
|
|
11031
|
+
function versorSetLocationAtPoint(tr, lnglat, point, panDelta, fixedBearing = true) {
|
|
11032
|
+
const pointLngLat = panSurfaceLocation(tr, point);
|
|
11033
|
+
let sourceLngLat = lnglat;
|
|
11034
|
+
if (panDelta) sourceLngLat = panSurfaceLocation(tr, point.sub(panDelta));
|
|
11035
|
+
else if (!tr.isPointOnMapSurface(point)) return;
|
|
11036
|
+
const vecToPixelCurrent = angularCoordinatesToSurfaceVector(pointLngLat);
|
|
11037
|
+
const vecToTarget = angularCoordinatesToSurfaceVector(sourceLngLat);
|
|
11038
|
+
const centerQuat = orientationFromLngLatBearing(tr.center, tr.bearing);
|
|
11039
|
+
const w = cross(createVec3f64(), vecToTarget, vecToPixelCurrent);
|
|
11040
|
+
const l = Math.sqrt(dot(w, w));
|
|
11041
|
+
const t = Math.acos(clamp(dot(vecToTarget, vecToPixelCurrent), -1, 1)) / 2;
|
|
11042
|
+
const s = Math.sin(t);
|
|
11043
|
+
const delta = l ? fromValues(w[1] / l * s, -w[0] / l * s, w[2] / l * s, Math.cos(t)) : fromValues(0, 0, 0, 1);
|
|
11044
|
+
const { lng: newCenterLng, lat: newCenterLat, bearing: newBearing } = lngLatBearingFromOrientation(multiply$1(createVec4f64(), centerQuat, delta));
|
|
11045
|
+
const oldLat = tr.center.lat;
|
|
11046
|
+
const finalLat = clamp(newCenterLat, -90, 90);
|
|
11047
|
+
const finalLng = fixedBearing ? fixedBearingLongitude(tr, point, panDelta, newCenterLng) : newCenterLng;
|
|
11048
|
+
tr.setCenter(new LngLat(wrap(finalLng, -180, 180), finalLat));
|
|
11049
|
+
if (!fixedBearing) tr.setBearing(newBearing);
|
|
11050
|
+
tr.setZoom(tr.zoom + getZoomAdjustment(oldLat, tr.center.lat));
|
|
11051
|
+
}
|
|
11052
|
+
/**
|
|
11053
|
+
* Returns the center longitude for a bearing-preserving drag.
|
|
11054
|
+
*
|
|
11055
|
+
* The swing longitude becomes ill-conditioned near the pole and the grabbed location slips away
|
|
11056
|
+
* from the cursor, so within the last ~12 degrees of latitude the cursor is treated as turning a
|
|
11057
|
+
* dial around the pole, blended in with a smoothstep anchored on {@link MAX_VALID_LATITUDE}, the
|
|
11058
|
+
* highest latitude the center can reach. The sweep comes from the raw pixel delta rather than a
|
|
11059
|
+
* round-tripped previous cursor position, which would lose its sign to cancellation at the pole,
|
|
11060
|
+
* and is damped within {@link DIAL_MIN_RADIUS_PIXELS} so it eases to nothing there instead of
|
|
11061
|
+
* being dropped, which would leave a spot where the drag could not move at all.
|
|
11062
|
+
* @param tr - The transform being dragged.
|
|
11063
|
+
* @param point - The cursor position.
|
|
11064
|
+
* @param panDelta - The drag's pixel delta, or undefined to use the swing longitude only.
|
|
11065
|
+
* @param newCenterLng - The swing target longitude.
|
|
11066
|
+
* @returns the center longitude to apply.
|
|
11067
|
+
*/
|
|
11068
|
+
function fixedBearingLongitude(tr, point, panDelta, newCenterLng) {
|
|
11069
|
+
const oldLng = tr.center.lng;
|
|
11070
|
+
const oldLat = tr.center.lat;
|
|
11071
|
+
const poleLat = oldLat >= 0 ? 90 : -90;
|
|
11072
|
+
const polePoint = tr.locationToScreenPoint(new LngLat(0, poleLat));
|
|
11073
|
+
const rx = point.x - polePoint.x, ry = point.y - polePoint.y;
|
|
11074
|
+
const r2 = rx * rx + ry * ry;
|
|
11075
|
+
const tRamp = clamp(1 - (MAX_VALID_LATITUDE - Math.abs(oldLat)) / 12, 0, 1);
|
|
11076
|
+
const dial = tRamp * tRamp * (3 - 2 * tRamp);
|
|
11077
|
+
const dLngSwing = mod(newCenterLng - oldLng + 180, 360) - 180;
|
|
11078
|
+
let dLngDial = 0;
|
|
11079
|
+
if (dial > 0 && panDelta) {
|
|
11080
|
+
const dTheta = (rx * panDelta.y - ry * panDelta.x) / Math.max(r2, 400);
|
|
11081
|
+
dLngDial = (poleLat > 0 ? 1 : -1) * dTheta * 180 / Math.PI;
|
|
11082
|
+
}
|
|
11083
|
+
return oldLng + (1 - dial) * dLngSwing + dial * dLngDial;
|
|
11084
|
+
}
|
|
11085
|
+
/**
|
|
10819
11086
|
* Given a normalized horizon plane in Ax+By+Cz+D=0 format, compute the center and radius of
|
|
10820
11087
|
* the circle in that plain that contains the entire visible portion of the unit sphere from horizon
|
|
10821
11088
|
* to horizon.
|
|
@@ -12477,6 +12744,7 @@ var GlobeTransform = class GlobeTransform {
|
|
|
12477
12744
|
if (!this.isGlobeRendering) return mercatorData;
|
|
12478
12745
|
const globeData = this._verticalPerspectiveTransform.getProjectionDataForCustomLayer(applyGlobeMatrix);
|
|
12479
12746
|
globeData.fallbackMatrix = mercatorData.mainMatrix;
|
|
12747
|
+
globeData.projectionTransition = this._globeness;
|
|
12480
12748
|
return globeData;
|
|
12481
12749
|
}
|
|
12482
12750
|
getFastPathSimpleProjectionMatrix(tileID) {
|
|
@@ -12578,12 +12846,17 @@ var VerticalPerspectiveCameraHelper = class VerticalPerspectiveCameraHelper {
|
|
|
12578
12846
|
tr.setCenter(new LngLat(exactCenter.lng + lngExactToHeuristic * heuristicFactor, exactCenter.lat + latExactToHeuristic * heuristicFactor).wrap());
|
|
12579
12847
|
tr.setZoom(oldZoom + getZoomAdjustment(oldCenterLat, tr.center.lat));
|
|
12580
12848
|
}
|
|
12581
|
-
|
|
12849
|
+
/**
|
|
12850
|
+
* Pans the globe by rotating it with a single quaternion that brings the grabbed location back
|
|
12851
|
+
* under the cursor. This stays consistent near and across the poles, where the previous
|
|
12852
|
+
* bearing-preserving mapping inverted and stalled (#5296).
|
|
12853
|
+
* @param deltas - The deltas accumulated for this frame.
|
|
12854
|
+
* @param tr - The transform to pan.
|
|
12855
|
+
* @param preZoomAroundLoc - The location that was under the cursor before this frame.
|
|
12856
|
+
*/
|
|
12857
|
+
handleMapControlsPan(deltas, tr, preZoomAroundLoc) {
|
|
12582
12858
|
if (!deltas.panDelta) return;
|
|
12583
|
-
|
|
12584
|
-
const oldZoom = tr.zoom;
|
|
12585
|
-
tr.setCenter(computeGlobePanCenter(deltas.panDelta, tr).wrap());
|
|
12586
|
-
tr.setZoom(oldZoom + getZoomAdjustment(oldLat, tr.center.lat));
|
|
12859
|
+
versorSetLocationAtPoint(tr, preZoomAroundLoc, deltas.around, deltas.panDelta);
|
|
12587
12860
|
}
|
|
12588
12861
|
cameraForBoxAndBearing(options, padding, bounds, bearing, tr) {
|
|
12589
12862
|
const result = cameraForBoxAndBearing(options, padding, bounds, bearing, tr);
|
|
@@ -12916,6 +13189,7 @@ var Style = class extends Evented {
|
|
|
12916
13189
|
this.imageManager = new ImageManager();
|
|
12917
13190
|
this.imageManager.setEventedParent(this);
|
|
12918
13191
|
this.imageManager.setMissingImageResolver(map._missingStyleImageResolver);
|
|
13192
|
+
this.patternAtlas = new PatternAtlas(this.imageManager);
|
|
12919
13193
|
const glyphLang = map._container?.lang || typeof document !== "undefined" && document.documentElement?.lang || void 0;
|
|
12920
13194
|
this.glyphManager = new GlyphManager(map._requestManager, options.localIdeographFontFamily, glyphLang);
|
|
12921
13195
|
this.lineAtlas = new LineAtlas(256, 512);
|
|
@@ -12937,12 +13211,10 @@ var Style = class extends Evented {
|
|
|
12937
13211
|
});
|
|
12938
13212
|
}
|
|
12939
13213
|
_setInitialValues() {
|
|
12940
|
-
this._spritesImagesIds = {};
|
|
12941
13214
|
this._layers = {};
|
|
12942
13215
|
this._order = [];
|
|
12943
13216
|
this.tileManagers = {};
|
|
12944
13217
|
this.zoomHistory = new ZoomHistory();
|
|
12945
|
-
this._availableImages = [];
|
|
12946
13218
|
this._imagesListDirty = false;
|
|
12947
13219
|
this._globalState = {};
|
|
12948
13220
|
this._serializedLayers = {};
|
|
@@ -13080,48 +13352,33 @@ var Style = class extends Evented {
|
|
|
13080
13352
|
}
|
|
13081
13353
|
}
|
|
13082
13354
|
}
|
|
13083
|
-
_loadSprite(sprite, isUpdate = false, completion = void 0) {
|
|
13355
|
+
async _loadSprite(sprite, isUpdate = false, completion = void 0) {
|
|
13084
13356
|
this.imageManager.setLoaded(false);
|
|
13085
13357
|
const abortController = new AbortController();
|
|
13086
13358
|
this._spriteRequest = abortController;
|
|
13087
13359
|
let err;
|
|
13088
|
-
|
|
13089
|
-
this.
|
|
13090
|
-
if (images)
|
|
13091
|
-
|
|
13092
|
-
const
|
|
13093
|
-
|
|
13094
|
-
|
|
13095
|
-
this._changedImages[id] = true;
|
|
13096
|
-
}
|
|
13097
|
-
for (const id in images[spriteId]) {
|
|
13098
|
-
const imageId = spriteId === "default" ? id : `${spriteId}:${id}`;
|
|
13099
|
-
this._spritesImagesIds[spriteId].push(imageId);
|
|
13100
|
-
if (imageId in this.imageManager.images) this.imageManager.updateImage(imageId, images[spriteId][id], false);
|
|
13101
|
-
else this.imageManager.addImage(imageId, images[spriteId][id]);
|
|
13102
|
-
if (isUpdate) this._changedImages[imageId] = true;
|
|
13103
|
-
}
|
|
13360
|
+
try {
|
|
13361
|
+
const images = await loadSprite(sprite, this.map._requestManager, this.map.getPixelRatio(), abortController);
|
|
13362
|
+
if (!images) return;
|
|
13363
|
+
for (const spriteId in images) {
|
|
13364
|
+
const { loaded, removed } = this.imageManager.setSpriteImages(spriteId, images[spriteId]);
|
|
13365
|
+
this._markImagesChanged(removed);
|
|
13366
|
+
if (isUpdate) this._markImagesChanged(loaded);
|
|
13104
13367
|
}
|
|
13105
|
-
}
|
|
13106
|
-
this._spriteRequest = null;
|
|
13368
|
+
} catch (error) {
|
|
13107
13369
|
err = error;
|
|
13108
13370
|
if (!abortController.signal.aborted) this.fire(new ErrorEvent(err));
|
|
13109
|
-
}
|
|
13371
|
+
} finally {
|
|
13372
|
+
this._spriteRequest = null;
|
|
13110
13373
|
this.imageManager.setLoaded(true);
|
|
13111
|
-
this._availableImages = this.imageManager.listImages();
|
|
13112
13374
|
if (isUpdate) this._changed = true;
|
|
13113
|
-
this.dispatcher.broadcast("SI", this.
|
|
13375
|
+
this.dispatcher.broadcast("SI", this.imageManager.listImages());
|
|
13114
13376
|
this.fire(new MapStyleDataEvent("data"));
|
|
13115
|
-
|
|
13116
|
-
}
|
|
13377
|
+
completion?.(err);
|
|
13378
|
+
}
|
|
13117
13379
|
}
|
|
13118
13380
|
_unloadSprite() {
|
|
13119
|
-
|
|
13120
|
-
this.imageManager.removeImage(id);
|
|
13121
|
-
this._changedImages[id] = true;
|
|
13122
|
-
}
|
|
13123
|
-
this._spritesImagesIds = {};
|
|
13124
|
-
this._availableImages = this.imageManager.listImages();
|
|
13381
|
+
this._markImagesChanged(this.imageManager.removeAllSpriteImages());
|
|
13125
13382
|
this._imagesListDirty = true;
|
|
13126
13383
|
this._changed = true;
|
|
13127
13384
|
this.fire(new MapStyleDataEvent("data"));
|
|
@@ -13193,7 +13450,7 @@ var Style = class extends Evented {
|
|
|
13193
13450
|
const changed = this._changed;
|
|
13194
13451
|
if (changed) {
|
|
13195
13452
|
if (this._imagesListDirty) {
|
|
13196
|
-
this.dispatcher.broadcast("SI", this.
|
|
13453
|
+
this.dispatcher.broadcast("SI", this.imageManager.listImages());
|
|
13197
13454
|
this._imagesListDirty = false;
|
|
13198
13455
|
}
|
|
13199
13456
|
const updatedIds = Object.keys(this._updatedLayers);
|
|
@@ -13218,9 +13475,10 @@ var Style = class extends Evented {
|
|
|
13218
13475
|
managersUsedBefore[id] = tileManager.used;
|
|
13219
13476
|
tileManager.used = false;
|
|
13220
13477
|
}
|
|
13478
|
+
const availableImages = this.imageManager.listImages();
|
|
13221
13479
|
for (const layerId of this._order) {
|
|
13222
13480
|
const layer = this._layers[layerId];
|
|
13223
|
-
layer.recalculate(parameters,
|
|
13481
|
+
layer.recalculate(parameters, availableImages);
|
|
13224
13482
|
if (!layer.isHidden(parameters.zoom) && layer.source) this.tileManagers[layer.source].used = true;
|
|
13225
13483
|
}
|
|
13226
13484
|
for (const id in managersUsedBefore) {
|
|
@@ -13382,8 +13640,14 @@ var Style = class extends Evented {
|
|
|
13382
13640
|
this.imageManager.removeImage(id);
|
|
13383
13641
|
this._afterImageUpdated(id);
|
|
13384
13642
|
}
|
|
13643
|
+
/**
|
|
13644
|
+
* Queues the tiles that depend on these images to be reloaded on the next update, which is
|
|
13645
|
+
* needed whenever an image appears, disappears or changes size.
|
|
13646
|
+
*/
|
|
13647
|
+
_markImagesChanged(ids) {
|
|
13648
|
+
for (const id of ids) this._changedImages[id] = true;
|
|
13649
|
+
}
|
|
13385
13650
|
_afterImageUpdated(id) {
|
|
13386
|
-
this._availableImages = this.imageManager.listImages();
|
|
13387
13651
|
this._changedImages[id] = true;
|
|
13388
13652
|
this._imagesListDirty = true;
|
|
13389
13653
|
this._changed = true;
|
|
@@ -13816,7 +14080,7 @@ var Style = class extends Evented {
|
|
|
13816
14080
|
}
|
|
13817
14081
|
}
|
|
13818
14082
|
const sourceResults = [];
|
|
13819
|
-
params.availableImages = this.
|
|
14083
|
+
params.availableImages = this.imageManager.listImages();
|
|
13820
14084
|
const serializedLayers = this._serializedAllLayers();
|
|
13821
14085
|
const layersAsSet = params.layers instanceof Set ? params.layers : Array.isArray(params.layers) ? new Set(params.layers) : null;
|
|
13822
14086
|
const paramsStrict = {
|
|
@@ -14053,14 +14317,10 @@ var Style = class extends Evented {
|
|
|
14053
14317
|
this.fire(new ErrorEvent(/* @__PURE__ */ new Error(`Sprite "${id}" doesn't exists on this map.`)));
|
|
14054
14318
|
return;
|
|
14055
14319
|
}
|
|
14056
|
-
|
|
14057
|
-
|
|
14058
|
-
this._changedImages[imageId] = true;
|
|
14059
|
-
}
|
|
14320
|
+
const changedImages = this.imageManager.removeSpriteImages(id);
|
|
14321
|
+
this._markImagesChanged(changedImages);
|
|
14060
14322
|
internalSpriteRepresentation.splice(internalSpriteRepresentation.findIndex((sprite) => sprite.id === id), 1);
|
|
14061
14323
|
this.stylesheet.sprite = internalSpriteRepresentation.length > 0 ? internalSpriteRepresentation : void 0;
|
|
14062
|
-
delete this._spritesImagesIds[id];
|
|
14063
|
-
this._availableImages = this.imageManager.listImages();
|
|
14064
14324
|
this._imagesListDirty = true;
|
|
14065
14325
|
this._changed = true;
|
|
14066
14326
|
this.fire(new MapStyleDataEvent("data"));
|
|
@@ -14115,8 +14375,7 @@ var Style = class extends Evented {
|
|
|
14115
14375
|
if (this.imageManager) {
|
|
14116
14376
|
this.imageManager.setEventedParent(null);
|
|
14117
14377
|
this.imageManager.destroy();
|
|
14118
|
-
this.
|
|
14119
|
-
this._spritesImagesIds = {};
|
|
14378
|
+
this.patternAtlas.destroy();
|
|
14120
14379
|
}
|
|
14121
14380
|
if (this.glyphManager) this.glyphManager.destroy();
|
|
14122
14381
|
for (const layerId in this._layers) {
|
|
@@ -14447,9 +14706,9 @@ function patternUniformValues(crossfade, painter, tile) {
|
|
|
14447
14706
|
};
|
|
14448
14707
|
}
|
|
14449
14708
|
function bgPatternUniformValues(image, crossfade, painter, tile) {
|
|
14450
|
-
const imagePosA = painter.
|
|
14451
|
-
const imagePosB = painter.
|
|
14452
|
-
const { width, height } = painter.
|
|
14709
|
+
const imagePosA = painter.patternAtlas.getPattern(image.from.toString());
|
|
14710
|
+
const imagePosB = painter.patternAtlas.getPattern(image.to.toString());
|
|
14711
|
+
const { width, height } = painter.patternAtlas.getPixelSize();
|
|
14453
14712
|
const numTiles = Math.pow(2, tile.tileID.overscaledZ);
|
|
14454
14713
|
const tileSizeAtNearestZoom = tile.tileSize * Math.pow(2, painter.transform.tileZoom) / numTiles;
|
|
14455
14714
|
const pixelX = tileSizeAtNearestZoom * (tile.tileID.canonical.x + tile.tileID.wrap * numTiles);
|
|
@@ -17252,7 +17511,7 @@ function drawBackground(painter, tileManager, layer, coords, renderOptions) {
|
|
|
17252
17511
|
});
|
|
17253
17512
|
if (image) {
|
|
17254
17513
|
context.activeTexture.set(gl.TEXTURE0);
|
|
17255
|
-
painter.
|
|
17514
|
+
painter.patternAtlas.bind(painter.context);
|
|
17256
17515
|
}
|
|
17257
17516
|
const crossfade = layer.getCrossfadeParameters();
|
|
17258
17517
|
for (const tileID of tileIDs) {
|
|
@@ -17933,6 +18192,7 @@ var Painter = class Painter {
|
|
|
17933
18192
|
this.options = options;
|
|
17934
18193
|
this.lineAtlas = style.lineAtlas;
|
|
17935
18194
|
this.imageManager = style.imageManager;
|
|
18195
|
+
this.patternAtlas = style.patternAtlas;
|
|
17936
18196
|
this.glyphManager = style.glyphManager;
|
|
17937
18197
|
this.symbolFadeChange = style.placement.symbolFadeChange(now());
|
|
17938
18198
|
this.imageManager.beginFrame();
|
|
@@ -18140,8 +18400,8 @@ var Painter = class Painter {
|
|
|
18140
18400
|
isPatternMissing(image) {
|
|
18141
18401
|
if (!image) return false;
|
|
18142
18402
|
if (!image.from || !image.to) return true;
|
|
18143
|
-
const imagePosA = this.
|
|
18144
|
-
const imagePosB = this.
|
|
18403
|
+
const imagePosA = this.patternAtlas.getPattern(image.from.toString());
|
|
18404
|
+
const imagePosB = this.patternAtlas.getPattern(image.to.toString());
|
|
18145
18405
|
return !imagePosA || !imagePosB;
|
|
18146
18406
|
}
|
|
18147
18407
|
/**
|
|
@@ -18402,6 +18662,14 @@ const defaultRollInertiaOptions = extend({
|
|
|
18402
18662
|
deceleration: 1e3,
|
|
18403
18663
|
maxSpeed: 360
|
|
18404
18664
|
}, defaultInertiaOptions);
|
|
18665
|
+
/**
|
|
18666
|
+
* The maximum age of a recorded gesture update, in milliseconds.
|
|
18667
|
+
*/
|
|
18668
|
+
const BUFFER_CUTOFF = 160;
|
|
18669
|
+
/**
|
|
18670
|
+
* The time window the gesture velocity is measured over, in milliseconds.
|
|
18671
|
+
*/
|
|
18672
|
+
const VELOCITY_WINDOW = 60;
|
|
18405
18673
|
var HandlerInertia = class {
|
|
18406
18674
|
constructor(map) {
|
|
18407
18675
|
this._map = map;
|
|
@@ -18418,12 +18686,41 @@ var HandlerInertia = class {
|
|
|
18418
18686
|
});
|
|
18419
18687
|
}
|
|
18420
18688
|
_drainInertiaBuffer() {
|
|
18421
|
-
const inertia = this._inertiaBuffer, currentTime = now()
|
|
18422
|
-
while (inertia.length > 0 && currentTime - inertia[0].time >
|
|
18689
|
+
const inertia = this._inertiaBuffer, currentTime = now();
|
|
18690
|
+
while (inertia.length > 0 && currentTime - inertia[0].time > BUFFER_CUTOFF) inertia.shift();
|
|
18691
|
+
}
|
|
18692
|
+
/**
|
|
18693
|
+
* Returns the entries the velocity is measured from: everything recorded within
|
|
18694
|
+
* {@link VELOCITY_WINDOW} before now, but never fewer than the last two, so that
|
|
18695
|
+
* inertia also works below two recorded updates per window.
|
|
18696
|
+
*/
|
|
18697
|
+
_getVelocityEntries() {
|
|
18698
|
+
const inertia = this._inertiaBuffer;
|
|
18699
|
+
const windowStart = now() - VELOCITY_WINDOW;
|
|
18700
|
+
let firstIndex = Math.max(0, inertia.length - 2);
|
|
18701
|
+
while (firstIndex > 0 && inertia[firstIndex - 1].time >= windowStart) firstIndex--;
|
|
18702
|
+
return inertia.slice(firstIndex);
|
|
18423
18703
|
}
|
|
18704
|
+
/**
|
|
18705
|
+
* Returns the ease which continues the gesture that has just ended.
|
|
18706
|
+
*
|
|
18707
|
+
* The velocity is measured over the time up to the release and not up to the last
|
|
18708
|
+
* recorded movement, so that a gesture held still before being released has a lower
|
|
18709
|
+
* velocity, down to no inertia at all. The delta of an entry happened before it was
|
|
18710
|
+
* recorded, so the first entry only marks the start of the measured interval; anchors
|
|
18711
|
+
* are the exception, as they describe the state at the moment of their entry.
|
|
18712
|
+
*
|
|
18713
|
+
* @param panInertiaOptions - overrides for the pan inertia defaults
|
|
18714
|
+
* @returns the ease options, or `undefined` when the measured interval holds no
|
|
18715
|
+
* movement, which terrain gestures produce by recording updates without any delta
|
|
18716
|
+
*/
|
|
18424
18717
|
_onMoveEnd(panInertiaOptions) {
|
|
18425
18718
|
this._drainInertiaBuffer();
|
|
18426
|
-
|
|
18719
|
+
const entries = this._getVelocityEntries();
|
|
18720
|
+
if (entries.length < 2) {
|
|
18721
|
+
this.clear();
|
|
18722
|
+
return;
|
|
18723
|
+
}
|
|
18427
18724
|
const deltas = {
|
|
18428
18725
|
zoom: 0,
|
|
18429
18726
|
bearing: 0,
|
|
@@ -18433,16 +18730,22 @@ var HandlerInertia = class {
|
|
|
18433
18730
|
pinchAround: void 0,
|
|
18434
18731
|
around: void 0
|
|
18435
18732
|
};
|
|
18436
|
-
for (const { settings } of
|
|
18733
|
+
for (const { settings } of entries) {
|
|
18734
|
+
if (settings.around) deltas.around = settings.around;
|
|
18735
|
+
if (settings.pinchAround) deltas.pinchAround = settings.pinchAround;
|
|
18736
|
+
}
|
|
18737
|
+
for (const { settings } of entries.slice(1)) {
|
|
18437
18738
|
deltas.zoom += settings.zoomDelta || 0;
|
|
18438
18739
|
deltas.bearing += settings.bearingDelta || 0;
|
|
18439
18740
|
deltas.pitch += settings.pitchDelta || 0;
|
|
18440
18741
|
deltas.roll += settings.rollDelta || 0;
|
|
18441
18742
|
if (settings.panDelta) deltas.pan._add(settings.panDelta);
|
|
18442
|
-
if (settings.around) deltas.around = settings.around;
|
|
18443
|
-
if (settings.pinchAround) deltas.pinchAround = settings.pinchAround;
|
|
18444
18743
|
}
|
|
18445
|
-
|
|
18744
|
+
if (!deltas.pan.mag() && !deltas.zoom && !deltas.bearing && !deltas.pitch && !deltas.roll) {
|
|
18745
|
+
this.clear();
|
|
18746
|
+
return;
|
|
18747
|
+
}
|
|
18748
|
+
const duration = now() - entries[0].time;
|
|
18446
18749
|
const easeOptions = {};
|
|
18447
18750
|
if (deltas.pan.mag()) {
|
|
18448
18751
|
const result = calculateEasing(deltas.pan.mag(), duration, extend({}, defaultPanInertiaOptions, panInertiaOptions || {}));
|
|
@@ -26196,6 +26499,17 @@ function applyAnchorClass(element, anchor, prefix) {
|
|
|
26196
26499
|
//#endregion
|
|
26197
26500
|
//#region src/ui/marker.ts
|
|
26198
26501
|
/**
|
|
26502
|
+
* Screen-pixel deltas applied when a focused draggable marker is moved with the arrow keys.
|
|
26503
|
+
*/
|
|
26504
|
+
const ARROW_KEY_DELTAS = {
|
|
26505
|
+
ArrowLeft: [-1, 0],
|
|
26506
|
+
ArrowRight: [1, 0],
|
|
26507
|
+
ArrowUp: [0, -1],
|
|
26508
|
+
ArrowDown: [0, 1]
|
|
26509
|
+
};
|
|
26510
|
+
const KEYBOARD_DRAG_SMALL_STEP = 1;
|
|
26511
|
+
const KEYBOARD_DRAG_LARGE_STEP = 10;
|
|
26512
|
+
/**
|
|
26199
26513
|
* The event class for marker drag events (`dragstart`, `drag` and `dragend`).
|
|
26200
26514
|
*
|
|
26201
26515
|
* @group Event Related
|
|
@@ -26270,6 +26584,30 @@ var Marker = class extends Evented {
|
|
|
26270
26584
|
this._onKeyPress = (e) => {
|
|
26271
26585
|
if (e.code === "Space" || e.code === "Enter") this.togglePopup();
|
|
26272
26586
|
};
|
|
26587
|
+
this._onKeyDown = (e) => {
|
|
26588
|
+
if (!this._defaultMarker || !this._draggable || !this._map || !this._lngLat) return;
|
|
26589
|
+
if (e.composedPath()[0] !== this._element) return;
|
|
26590
|
+
if (e.altKey || e.ctrlKey || e.metaKey) return;
|
|
26591
|
+
const delta = ARROW_KEY_DELTAS[e.key];
|
|
26592
|
+
if (!delta) return;
|
|
26593
|
+
e.preventDefault();
|
|
26594
|
+
e.stopPropagation();
|
|
26595
|
+
const step = e.shiftKey ? KEYBOARD_DRAG_LARGE_STEP : KEYBOARD_DRAG_SMALL_STEP;
|
|
26596
|
+
const pos = this._map.project(this._lngLat);
|
|
26597
|
+
this.setLngLat(this._map.unproject(new Point(pos.x + delta[0] * step, pos.y + delta[1] * step)));
|
|
26598
|
+
if (!this._keyboardDragActive) {
|
|
26599
|
+
this._keyboardDragActive = true;
|
|
26600
|
+
this.fire(new MarkerDragEvent("dragstart"));
|
|
26601
|
+
}
|
|
26602
|
+
this.fire(new MarkerDragEvent("drag"));
|
|
26603
|
+
};
|
|
26604
|
+
this._onKeyUp = (e) => {
|
|
26605
|
+
if (!ARROW_KEY_DELTAS[e.key]) return;
|
|
26606
|
+
this._endKeyboardDrag();
|
|
26607
|
+
};
|
|
26608
|
+
this._onBlur = () => {
|
|
26609
|
+
this._endKeyboardDrag();
|
|
26610
|
+
};
|
|
26273
26611
|
this._onMapClick = (e) => {
|
|
26274
26612
|
const targetElement = e.originalEvent.target;
|
|
26275
26613
|
const element = this._element;
|
|
@@ -26340,6 +26678,8 @@ var Marker = class extends Evented {
|
|
|
26340
26678
|
this._subpixelPositioning = options?.subpixelPositioning || false;
|
|
26341
26679
|
this._isDragging = false;
|
|
26342
26680
|
this._roleManaged = false;
|
|
26681
|
+
this._tabIndexManaged = false;
|
|
26682
|
+
this._keyboardDragActive = false;
|
|
26343
26683
|
this._state = "inactive";
|
|
26344
26684
|
this._rotation = options?.rotation || 0;
|
|
26345
26685
|
this._rotationAlignment = options?.rotationAlignment || "auto";
|
|
@@ -26515,6 +26855,11 @@ var Marker = class extends Evented {
|
|
|
26515
26855
|
delete this._map;
|
|
26516
26856
|
}
|
|
26517
26857
|
this._element.removeEventListener("click", this._onClick);
|
|
26858
|
+
this._element.removeEventListener("keydown", this._onKeyDown);
|
|
26859
|
+
this._element.removeEventListener("keyup", this._onKeyUp);
|
|
26860
|
+
this._element.removeEventListener("blur", this._onBlur);
|
|
26861
|
+
this._element.removeEventListener("keypress", this._onKeyPress);
|
|
26862
|
+
this._keyboardDragActive = false;
|
|
26518
26863
|
this._element.remove();
|
|
26519
26864
|
if (this._popup) this._popup.remove();
|
|
26520
26865
|
return this;
|
|
@@ -26584,7 +26929,6 @@ var Marker = class extends Evented {
|
|
|
26584
26929
|
this._popup.remove();
|
|
26585
26930
|
this._popup = null;
|
|
26586
26931
|
this._element.removeEventListener("keypress", this._onKeyPress);
|
|
26587
|
-
if (!this._originalTabIndex) this._element.removeAttribute("tabindex");
|
|
26588
26932
|
}
|
|
26589
26933
|
if (popup) {
|
|
26590
26934
|
if (!("offset" in popup.options)) {
|
|
@@ -26602,10 +26946,9 @@ var Marker = class extends Evented {
|
|
|
26602
26946
|
} : this._offset;
|
|
26603
26947
|
}
|
|
26604
26948
|
this._popup = popup;
|
|
26605
|
-
this._originalTabIndex = this._element.getAttribute("tabindex");
|
|
26606
|
-
if (!this._originalTabIndex) this._element.setAttribute("tabindex", "0");
|
|
26607
26949
|
this._element.addEventListener("keypress", this._onKeyPress);
|
|
26608
26950
|
}
|
|
26951
|
+
this._updateTabIndex();
|
|
26609
26952
|
this._updateAccessibilityRole();
|
|
26610
26953
|
return this;
|
|
26611
26954
|
}
|
|
@@ -26624,6 +26967,12 @@ var Marker = class extends Evented {
|
|
|
26624
26967
|
this._subpixelPositioning = value;
|
|
26625
26968
|
return this;
|
|
26626
26969
|
}
|
|
26970
|
+
_endKeyboardDrag() {
|
|
26971
|
+
if (this._keyboardDragActive) {
|
|
26972
|
+
this._keyboardDragActive = false;
|
|
26973
|
+
this.fire(new MarkerDragEvent("dragend"));
|
|
26974
|
+
}
|
|
26975
|
+
}
|
|
26627
26976
|
/**
|
|
26628
26977
|
* Returns the {@link Popup} instance that is bound to the {@link Marker}.
|
|
26629
26978
|
* @returns popup
|
|
@@ -26760,7 +27109,10 @@ var Marker = class extends Evented {
|
|
|
26760
27109
|
return this._element.classList.toggle(className);
|
|
26761
27110
|
}
|
|
26762
27111
|
/**
|
|
26763
|
-
* Sets the `draggable` property and functionality of the marker
|
|
27112
|
+
* Sets the `draggable` property and functionality of the marker.
|
|
27113
|
+
* A draggable default marker is also keyboard focusable and movable with the
|
|
27114
|
+
* arrow keys (see {@link MarkerOptions.draggable}); custom marker elements keep
|
|
27115
|
+
* their focusability and keyboard behavior application-owned.
|
|
26764
27116
|
* @param shouldBeDraggable - Turns drag functionality on/off
|
|
26765
27117
|
*/
|
|
26766
27118
|
setDraggable(shouldBeDraggable) {
|
|
@@ -26775,6 +27127,19 @@ var Marker = class extends Evented {
|
|
|
26775
27127
|
this._map.off("touchstart", this._addDragHandler);
|
|
26776
27128
|
}
|
|
26777
27129
|
}
|
|
27130
|
+
if (this._defaultMarker) {
|
|
27131
|
+
if (this._draggable) {
|
|
27132
|
+
this._element.addEventListener("keydown", this._onKeyDown);
|
|
27133
|
+
this._element.addEventListener("keyup", this._onKeyUp);
|
|
27134
|
+
this._element.addEventListener("blur", this._onBlur);
|
|
27135
|
+
} else {
|
|
27136
|
+
this._element.removeEventListener("keydown", this._onKeyDown);
|
|
27137
|
+
this._element.removeEventListener("keyup", this._onKeyUp);
|
|
27138
|
+
this._element.removeEventListener("blur", this._onBlur);
|
|
27139
|
+
this._endKeyboardDrag();
|
|
27140
|
+
}
|
|
27141
|
+
}
|
|
27142
|
+
this._updateTabIndex();
|
|
26778
27143
|
this._updateAccessibilityRole();
|
|
26779
27144
|
return this;
|
|
26780
27145
|
}
|
|
@@ -26786,6 +27151,24 @@ var Marker = class extends Evented {
|
|
|
26786
27151
|
return this._draggable;
|
|
26787
27152
|
}
|
|
26788
27153
|
/**
|
|
27154
|
+
* Keep the marker element focusable while it has built-in keyboard behavior.
|
|
27155
|
+
* A popup makes any marker element interactive; dragging only manages
|
|
27156
|
+
* focusability for the default marker so custom elements stay
|
|
27157
|
+
* application-owned (#7790). A tabindex supplied by the application is
|
|
27158
|
+
* never added, changed, or removed here.
|
|
27159
|
+
*/
|
|
27160
|
+
_updateTabIndex() {
|
|
27161
|
+
if (!!this._popup || this._defaultMarker && this._draggable) {
|
|
27162
|
+
if (!this._element.hasAttribute("tabindex")) {
|
|
27163
|
+
this._element.setAttribute("tabindex", "0");
|
|
27164
|
+
this._tabIndexManaged = true;
|
|
27165
|
+
}
|
|
27166
|
+
} else if (this._tabIndexManaged) {
|
|
27167
|
+
if (this._element.getAttribute("tabindex") === "0") this._element.removeAttribute("tabindex");
|
|
27168
|
+
this._tabIndexManaged = false;
|
|
27169
|
+
}
|
|
27170
|
+
}
|
|
27171
|
+
/**
|
|
26789
27172
|
* Keep the default marker role aligned with interactivity.
|
|
26790
27173
|
* Default markers need a role because `aria-label` is set in {@link Marker.addTo}.
|
|
26791
27174
|
* Non-interactive markers use `role=img`; interactive ones (draggable or with a popup) use `role=button`.
|