Skip to content

Commit 211cb71

Browse files
author
Les Moffat
committed
- fix bug that prevented spacebox from being set correclty when style was changed. - add simple lerping between space color and radial gradient to make the experince less jarring
1 parent de13931 commit 211cb71

File tree

6 files changed

+106
-19
lines changed

6 files changed

+106
-19
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@maptiler/sdk",
3-
"version": "3.3.0-rc2",
3+
"version": "3.3.0-rc3",
44
"description": "The Javascript & TypeScript map SDK tailored for MapTiler Cloud",
55
"author": "MapTiler",
66
"module": "dist/maptiler-sdk.mjs",

src/Map.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import { MaptilerProjectionControl } from "./controls/MaptilerProjectionControl"
4141
import { Telemetry } from "./Telemetry";
4242
import { CubemapDefinition, CubemapLayer, CubemapLayerConstructorOptions } from "./custom-layers/CubemapLayer";
4343
import { GradientDefinition, RadialGradientLayer, RadialGradientLayerOptions } from "./custom-layers/RadialGradientLayer";
44-
import extractCustomLayerStyle from "./custom-layers/extractCustomLayerStyle";
44+
import extractCustomLayerStyle, { StyleSpecificationWithMetaData } from "./custom-layers/extractCustomLayerStyle";
4545

4646
export type LoadWithTerrainEvent = {
4747
type: "loadWithTerrain";
@@ -232,6 +232,20 @@ export class Map extends maplibregl.Map {
232232
});
233233
}
234234

235+
private setSpaceFromStyle({ style }: { style?: StyleSpecificationWithMetaData }) {
236+
if (!style?.metadata?.maptiler?.space) {
237+
return;
238+
}
239+
this.space?.setCubemap(style.metadata.maptiler.space);
240+
}
241+
242+
private setHaloFromStyle({ style }: { style?: StyleSpecificationWithMetaData }) {
243+
if (!style?.metadata?.maptiler?.halo) {
244+
return;
245+
}
246+
void this.halo?.setGradient(style.metadata.maptiler.halo);
247+
}
248+
235249
private setSpaceFromCurrentStyle() {
236250
const spaceOptionsFromStyleSpec = extractCustomLayerStyle<CubemapDefinition>({ map: this, property: "space" });
237251
if (spaceOptionsFromStyleSpec && this.space) {
@@ -243,7 +257,7 @@ export class Map extends maplibregl.Map {
243257
private setHaloFromCurrentStyle() {
244258
const haloOptionsFromStyleSpec = extractCustomLayerStyle<GradientDefinition>({ map: this, property: "halo" });
245259
if (haloOptionsFromStyleSpec && this.halo) {
246-
this.halo.setGradient(haloOptionsFromStyleSpec);
260+
void this.halo.setGradient(haloOptionsFromStyleSpec);
247261
return;
248262
}
249263
}
@@ -945,13 +959,13 @@ export class Map extends maplibregl.Map {
945959

946960
if (typeof styleInfo.style !== "string" && !styleInfo.requiresUrlMonitoring) {
947961
if (this.space) {
948-
this.setSpaceFromCurrentStyle();
962+
this.setSpaceFromStyle({ style });
949963
} else {
950964
this.initSpace({ before });
951965
}
952966

953967
if (this.halo) {
954-
this.setHaloFromCurrentStyle();
968+
this.setHaloFromStyle({ style });
955969
} else {
956970
this.initHalo({ before });
957971
}

src/custom-layers/CubemapLayer/CubemapLayer.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import vertexShaderSource from "./cubemap.vert.glsl?raw";
99
import fragmentShaderSource from "./cubemap.frag.glsl?raw";
1010
import { loadCubemapTexture } from "./loadCubemapTexture";
1111
import type { CubemapDefinition, CubemapFaces, CubemapLayerConstructorOptions } from "./types";
12+
import { lerpVec4 } from "../../utils/math-utils";
1213

1314
const SPACE_IMAGES_BASE_URL = "api.maptiler.com/resources/space";
1415

@@ -64,6 +65,12 @@ class CubemapLayer implements CustomLayerInterface {
6465
private currentFadeOpacity: number = 0.0;
6566
private cubeMapNeedsUpdate: boolean = false;
6667
private bgColor: Vec4;
68+
69+
private previousBgColor: Vec4 = [0, 0, 0, 0];
70+
private targetBgColor: Vec4 = [0, 0, 0, 0];
71+
72+
private transitionDelta: number = 0.0;
73+
6774
private gl!: WebGLContext;
6875

6976
private cubemap?: Object3D<(typeof ATTRIBUTES_KEYS)[number], (typeof UNIFORMS_KEYS)[number]>;
@@ -79,7 +86,6 @@ class CubemapLayer implements CustomLayerInterface {
7986

8087
public updateCubemap(): void {
8188
this.useCubemapTexture = this.faces !== null;
82-
8389
const uniformsKeys = UNIFORMS_KEYS.filter((uniformKey) => {
8490
if (uniformKey === "cubeSampler") {
8591
return this.useCubemapTexture;
@@ -101,6 +107,7 @@ class CubemapLayer implements CustomLayerInterface {
101107
indices: INDICES,
102108
});
103109
this.cubeMapNeedsUpdate = true;
110+
this.animateTo();
104111
}
105112

106113
public onAdd(map: MapSDK, gl: WebGLRenderingContext | WebGL2RenderingContext): void {
@@ -133,6 +140,18 @@ class CubemapLayer implements CustomLayerInterface {
133140
}
134141
}
135142

143+
private animateTo() {
144+
const animateTo = () => {
145+
if (this.transitionDelta < 1.0) {
146+
requestAnimationFrame(animateTo);
147+
this.bgColor = lerpVec4(this.previousBgColor, this.targetBgColor, this.transitionDelta);
148+
this.transitionDelta += 0.075;
149+
this.map.triggerRepaint();
150+
}
151+
};
152+
requestAnimationFrame(animateTo);
153+
}
154+
136155
private animateIn(): void {
137156
const animateIn = () => {
138157
if (this.currentFadeOpacity < 1.0) {
@@ -226,7 +245,9 @@ class CubemapLayer implements CustomLayerInterface {
226245
}
227246

228247
public setCubemap(cubemap: CubemapDefinition): void {
229-
this.bgColor = parseColorStringToVec4(cubemap.color);
248+
this.targetBgColor = parseColorStringToVec4(cubemap.color);
249+
this.previousBgColor = this.bgColor;
250+
this.transitionDelta = 0.0;
230251
this.faces = getCubemapFaces(cubemap);
231252
this.updateCubemap();
232253
this.cubeMapNeedsUpdate = true;

src/custom-layers/RadialGradientLayer/RadialGradientLayer.ts

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { createObject3D, parseColorStringToVec4, type Object3D } from "../../uti
77
import vertexShaderSource from "./radialGradient.vert.glsl?raw";
88
import fragmentShaderSource from "./radialGradient.frag.glsl?raw";
99
import type { GradientDefinition, RadialGradientLayerOptions } from "./types";
10+
import { lerp } from "../../utils/math-utils";
1011

1112
const HALO_MAX_DISTANCE = 2;
1213
// 1 = globe radius
@@ -37,6 +38,8 @@ const defaultConstructorOptions: RadialGradientLayerOptions = {
3738
],
3839
};
3940

41+
const DELTA_CHANGE = 0.075;
42+
4043
export class RadialGradientLayer implements CustomLayerInterface {
4144
public id: string = "Halo Layer";
4245
public type: CustomLayerInterface["type"] = "custom";
@@ -45,6 +48,8 @@ export class RadialGradientLayer implements CustomLayerInterface {
4548
private gradient: GradientDefinition;
4649
private scale: number = 0.0;
4750

51+
private animationDelta: number = 0.0;
52+
4853
private map!: MapSDK;
4954
private plane?: Object3D<(typeof ATTRIBUTES_KEYS)[number], (typeof UNIFORMS_KEYS)[number]>;
5055

@@ -71,14 +76,41 @@ export class RadialGradientLayer implements CustomLayerInterface {
7176
vertices: VERTICES,
7277
});
7378

74-
const animate = () => {
75-
if (this.scale < this.gradient.scale) {
76-
this.scale += 0.05;
77-
this.map.triggerRepaint();
78-
requestAnimationFrame(animate);
79-
}
80-
};
81-
animate();
79+
void this.animateIn();
80+
}
81+
82+
private async animateIn() {
83+
return new Promise<void>((resolve) => {
84+
this.animationDelta = 0;
85+
const animate = () => {
86+
if (this.animationDelta < 1) {
87+
this.scale = lerp(0, this.gradient.scale, this.animationDelta);
88+
this.animationDelta += DELTA_CHANGE;
89+
this.map.triggerRepaint();
90+
requestAnimationFrame(animate);
91+
return;
92+
}
93+
resolve();
94+
};
95+
animate();
96+
});
97+
}
98+
99+
private async animateOut() {
100+
this.animationDelta = 0;
101+
return new Promise<void>((resolve) => {
102+
const animate = () => {
103+
if (this.animationDelta < 1) {
104+
this.scale = lerp(this.gradient.scale, 0, this.animationDelta);
105+
this.animationDelta += DELTA_CHANGE;
106+
this.map.triggerRepaint();
107+
requestAnimationFrame(animate);
108+
return;
109+
}
110+
resolve();
111+
};
112+
animate();
113+
});
82114
}
83115

84116
public onRemove(_map: MapSDK, gl: WebGLRenderingContext | WebGL2RenderingContext): void {
@@ -187,8 +219,10 @@ export class RadialGradientLayer implements CustomLayerInterface {
187219
* Value settings methods
188220
*/
189221

190-
public setGradient(gradient: GradientDefinition): void {
222+
public async setGradient(gradient: GradientDefinition): Promise<void> {
223+
await this.animateOut();
191224
this.gradient = gradient;
225+
await this.animateIn();
192226
}
193227

194228
public show(): void {

src/utils/math-utils.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { Vec4 } from "./webgl-utils";
2+
13
function minMax(value: number, min: number, max: number): number {
24
return Math.min(max, Math.max(min, value));
35
}
@@ -10,4 +12,20 @@ function diagonalOfSquare(side: number): number {
1012
return Math.sqrt(2) * side;
1113
}
1214

13-
export { minMax, normalize, diagonalOfSquare };
15+
type Lerpable = [number, number, number, number] | Vec4;
16+
17+
function lerpVec4(a: Lerpable, b: Lerpable, t: number): Vec4 {
18+
//prettier-ignore
19+
return [
20+
lerp(a[0], b[0], t),
21+
lerp(a[1], b[1], t),
22+
lerp(a[2], b[2], t),
23+
lerp(a[3], b[3], t),
24+
];
25+
}
26+
27+
function lerp(a: number, b: number, t: number): number {
28+
return a + (b - a) * t;
29+
}
30+
31+
export { minMax, normalize, diagonalOfSquare, lerpVec4, lerp };

0 commit comments

Comments
 (0)