fix(web): soften wave glow and follow liquid shape
ci / ts / ts (packages + web) (push) Successful in 2m25s
ci / ts / ts (packages + web) (push) Successful in 2m25s
This commit is contained in:
1 parent
7b7ce78de8
commit
9223516547
1 file changed
+21
-13
@@ -65,16 +65,9 @@ export function drawOrb(ctx: CanvasRenderingContext2D, cx: number, cy: number, r
|
|||||||
|
|
||||||
export function drawLiquid(ctx: CanvasRenderingContext2D, cx: number, cy: number, r: number, s: WaveState, t: number) {
|
export function drawLiquid(ctx: CanvasRenderingContext2D, cx: number, cy: number, r: number, s: WaveState, t: number) {
|
||||||
const cols = s.colors.map(rgb) as [Rgb, Rgb, Rgb];
|
const cols = s.colors.map(rgb) as [Rgb, Rgb, Rgb];
|
||||||
const glow = ctx.createRadialGradient(cx, cy, r * 0.4, cx, cy, r * 1.6);
|
// Reuse the animated silhouettes for the halo so it follows every deformation.
|
||||||
glow.addColorStop(0, rgba(cols[0], 0.3 + s.pulse * 0.3));
|
const shapes = Array.from({ length: 3 }, (_, L) => {
|
||||||
glow.addColorStop(1, rgba(cols[0], 0));
|
const path = new Path2D();
|
||||||
ctx.fillStyle = glow;
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.arc(cx, cy, r * 1.6, 0, Math.PI * 2);
|
|
||||||
ctx.fill();
|
|
||||||
ctx.globalCompositeOperation = s.dark ? 'lighter' : 'source-over';
|
|
||||||
for (let L = 0; L < 3; L++) {
|
|
||||||
ctx.beginPath();
|
|
||||||
const P = 140;
|
const P = 140;
|
||||||
for (let j = 0; j <= P; j++) {
|
for (let j = 0; j <= P; j++) {
|
||||||
const th = (j / P) * Math.PI * 2;
|
const th = (j / P) * Math.PI * 2;
|
||||||
@@ -88,9 +81,24 @@ export function drawLiquid(ctx: CanvasRenderingContext2D, cx: number, cy: number
|
|||||||
const rr = r * (0.86 - L * 0.07) * w;
|
const rr = r * (0.86 - L * 0.07) * w;
|
||||||
const x = cx + Math.cos(th) * rr;
|
const x = cx + Math.cos(th) * rr;
|
||||||
const y = cy + Math.sin(th) * rr;
|
const y = cy + Math.sin(th) * rr;
|
||||||
if (j) ctx.lineTo(x, y);
|
if (j) path.lineTo(x, y);
|
||||||
else ctx.moveTo(x, y);
|
else path.moveTo(x, y);
|
||||||
}
|
}
|
||||||
|
path.closePath();
|
||||||
|
return path;
|
||||||
|
});
|
||||||
|
|
||||||
|
ctx.save();
|
||||||
|
// Two soft falloffs avoid a visible circular boundary, even at peak pulse.
|
||||||
|
for (const [blur, opacity] of [[0.2, 0.14], [0.09, 0.18]] as const) {
|
||||||
|
ctx.filter = `blur(${r * blur}px)`;
|
||||||
|
ctx.fillStyle = rgba(cols[0], opacity * (0.8 + s.pulse * 0.6));
|
||||||
|
ctx.fill(shapes[0]!);
|
||||||
|
}
|
||||||
|
ctx.restore();
|
||||||
|
|
||||||
|
ctx.globalCompositeOperation = s.dark ? 'lighter' : 'source-over';
|
||||||
|
for (let L = 0; L < shapes.length; L++) {
|
||||||
const ox = Math.cos(t * 0.4 + L * 2) * r * 0.3;
|
const ox = Math.cos(t * 0.4 + L * 2) * r * 0.3;
|
||||||
const oy = Math.sin(t * 0.5 + L) * r * 0.3;
|
const oy = Math.sin(t * 0.5 + L) * r * 0.3;
|
||||||
const g = ctx.createRadialGradient(cx + ox, cy + oy, 0, cx, cy, r * 1.1);
|
const g = ctx.createRadialGradient(cx + ox, cy + oy, 0, cx, cy, r * 1.1);
|
||||||
@@ -98,7 +106,7 @@ export function drawLiquid(ctx: CanvasRenderingContext2D, cx: number, cy: number
|
|||||||
g.addColorStop(1, rgba(cols[L]!, 0.25));
|
g.addColorStop(1, rgba(cols[L]!, 0.25));
|
||||||
ctx.fillStyle = g;
|
ctx.fillStyle = g;
|
||||||
ctx.globalAlpha = s.dark ? 0.6 : 0.75;
|
ctx.globalAlpha = s.dark ? 0.6 : 0.75;
|
||||||
ctx.fill();
|
ctx.fill(shapes[L]!);
|
||||||
}
|
}
|
||||||
ctx.globalAlpha = 1;
|
ctx.globalAlpha = 1;
|
||||||
ctx.globalCompositeOperation = 'source-over';
|
ctx.globalCompositeOperation = 'source-over';
|
||||||
|
|||||||
Reference in new issue
Block a user