Skip to content

Commit 8e97d94

Browse files
committed
fix: background animation
1 parent d397e97 commit 8e97d94

File tree

1 file changed

+68
-31
lines changed

1 file changed

+68
-31
lines changed

app/components/BackgroundAnimation.tsx

Lines changed: 68 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,10 @@ export function BackgroundAnimation() {
1919

2020
const canvas = canvasRef.current
2121

22-
const morphDuration = 4000
22+
let morphDuration = 2000
2323
const waitDuration = 1000 * 60 * 2
2424

25-
function easeInOutCubic(t: number, b: number, c: number, d: number) {
26-
if ((t /= d / 2) < 1) return (c / 2) * t * t * t + b
27-
return (c / 2) * ((t -= 2) * t * t + 2) + b
28-
}
25+
const easingFn = cubicBezier(0.645, 0.045, 0.355, 1.0)
2926

3027
if (canvas) {
3128
const ctx = canvas.getContext('2d')!
@@ -67,8 +64,8 @@ export function BackgroundAnimation() {
6764
return array
6865
}
6966

70-
let currentBlobs = createBlobs()
71-
let interBlobs = currentBlobs
67+
let startBlobs = createBlobs()
68+
let currentBlobs = startBlobs
7269
let targetBlobs: ReturnType<typeof createBlobs> = []
7370

7471
function start() {
@@ -78,11 +75,10 @@ export function BackgroundAnimation() {
7875
if (rafId) {
7976
cancelAnimationFrame(rafId)
8077
}
81-
const parent = canvas!.parentElement
82-
canvas!.width = parent!.clientWidth
83-
canvas!.height = parent!.clientHeight
78+
canvas!.width = document.documentElement.clientWidth
79+
canvas!.height = document.documentElement.clientHeight
8480

85-
currentBlobs = interBlobs
81+
startBlobs = JSON.parse(JSON.stringify(currentBlobs))
8682
targetBlobs = createBlobs()
8783
startTime = performance.now()
8884
animate()
@@ -92,45 +88,64 @@ export function BackgroundAnimation() {
9288
ctx.clearRect(0, 0, canvas!.width, canvas!.height)
9389

9490
const time = performance.now() - startTime
95-
const progress = easeInOutCubic(time, 0, 1, morphDuration)
91+
const progress = time / morphDuration
92+
const easedProgress = easingFn(progress)
9693

9794
// Draw the blobs
98-
currentBlobs.forEach((blob, i) => {
95+
startBlobs.forEach((startBlob, i) => {
9996
const targetBlob = targetBlobs[i]
100-
interBlobs[i].x = blob.x + (targetBlob.x - blob.x) * progress
101-
interBlobs[i].y = blob.y + (targetBlob.y - blob.y) * progress
97+
98+
currentBlobs[i].x = interpolate(
99+
startBlob.x,
100+
targetBlob.x,
101+
easedProgress
102+
)
103+
currentBlobs[i].y = interpolate(
104+
startBlob.y,
105+
targetBlob.y,
106+
easedProgress
107+
)
102108

103109
const gradient = ctx.createRadialGradient(
104-
interBlobs[i].x,
105-
interBlobs[i].y,
110+
currentBlobs[i].x,
111+
currentBlobs[i].y,
106112
0,
107-
interBlobs[i].x,
108-
interBlobs[i].y,
109-
interBlobs[i].r
113+
currentBlobs[i].x,
114+
currentBlobs[i].y,
115+
currentBlobs[i].r
110116
)
111117

112-
interBlobs[i].colorH =
113-
blob.colorH + (targetBlob.colorH - blob.colorH) * progress
114-
interBlobs[i].colorS =
115-
blob.colorS + (targetBlob.colorS - blob.colorS) * progress
116-
interBlobs[i].colorL =
117-
blob.colorL + (targetBlob.colorL - blob.colorL) * progress
118+
currentBlobs[i].colorH = interpolate(
119+
startBlob.colorH,
120+
targetBlob.colorH,
121+
easedProgress
122+
)
123+
currentBlobs[i].colorS = interpolate(
124+
startBlob.colorS,
125+
targetBlob.colorS,
126+
easedProgress
127+
)
128+
currentBlobs[i].colorL = interpolate(
129+
startBlob.colorL,
130+
targetBlob.colorL,
131+
easedProgress
132+
)
118133

119134
gradient.addColorStop(
120135
0,
121-
`hsla(${interBlobs[i].colorH}, ${interBlobs[i].colorS}%, ${interBlobs[i].colorL}%, 1)`
136+
`hsla(${currentBlobs[i].colorH}, ${currentBlobs[i].colorS}%, ${currentBlobs[i].colorL}%, 1)`
122137
)
123138
gradient.addColorStop(
124139
1,
125-
`hsla(${interBlobs[i].colorH}, ${interBlobs[i].colorS}%, ${interBlobs[i].colorL}%, 0)`
140+
`hsla(${currentBlobs[i].colorH}, ${currentBlobs[i].colorS}%, ${currentBlobs[i].colorL}%, 0)`
126141
)
127142

128143
ctx.fillStyle = gradient
129144
ctx.beginPath()
130145
ctx.arc(
131-
interBlobs[i].x,
132-
interBlobs[i].y,
133-
interBlobs[i].r,
146+
currentBlobs[i].x,
147+
currentBlobs[i].y,
148+
currentBlobs[i].r,
134149
0,
135150
Math.PI * 2
136151
)
@@ -141,6 +156,7 @@ export function BackgroundAnimation() {
141156
rafId = requestAnimationFrame(animate)
142157
} else {
143158
timeout = setTimeout(() => {
159+
morphDuration = 4000
144160
start()
145161
}, waitDuration)
146162
}
@@ -178,3 +194,24 @@ export function BackgroundAnimation() {
178194
</div>
179195
)
180196
}
197+
198+
function cubicBezier(p1x, p1y, p2x, p2y) {
199+
return function (t) {
200+
const cx = 3 * p1x
201+
const bx = 3 * (p2x - p1x) - cx
202+
const ax = 1 - cx - bx
203+
204+
const cy = 3 * p1y
205+
const by = 3 * (p2y - p1y) - cy
206+
const ay = 1 - cy - by
207+
208+
const x = ((ax * t + bx) * t + cx) * t
209+
const y = ((ay * t + by) * t + cy) * t
210+
211+
return y
212+
}
213+
}
214+
215+
function interpolate(start: number, end: number, progress: number) {
216+
return start + (end - start) * progress
217+
}

0 commit comments

Comments
 (0)