@@ -19,13 +19,10 @@ export function BackgroundAnimation() {
19
19
20
20
const canvas = canvasRef . current
21
21
22
- const morphDuration = 4000
22
+ let morphDuration = 2000
23
23
const waitDuration = 1000 * 60 * 2
24
24
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 )
29
26
30
27
if ( canvas ) {
31
28
const ctx = canvas . getContext ( '2d' ) !
@@ -67,8 +64,8 @@ export function BackgroundAnimation() {
67
64
return array
68
65
}
69
66
70
- let currentBlobs = createBlobs ( )
71
- let interBlobs = currentBlobs
67
+ let startBlobs = createBlobs ( )
68
+ let currentBlobs = startBlobs
72
69
let targetBlobs : ReturnType < typeof createBlobs > = [ ]
73
70
74
71
function start ( ) {
@@ -78,11 +75,10 @@ export function BackgroundAnimation() {
78
75
if ( rafId ) {
79
76
cancelAnimationFrame ( rafId )
80
77
}
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
84
80
85
- currentBlobs = interBlobs
81
+ startBlobs = JSON . parse ( JSON . stringify ( currentBlobs ) )
86
82
targetBlobs = createBlobs ( )
87
83
startTime = performance . now ( )
88
84
animate ( )
@@ -92,45 +88,64 @@ export function BackgroundAnimation() {
92
88
ctx . clearRect ( 0 , 0 , canvas ! . width , canvas ! . height )
93
89
94
90
const time = performance . now ( ) - startTime
95
- const progress = easeInOutCubic ( time , 0 , 1 , morphDuration )
91
+ const progress = time / morphDuration
92
+ const easedProgress = easingFn ( progress )
96
93
97
94
// Draw the blobs
98
- currentBlobs . forEach ( ( blob , i ) => {
95
+ startBlobs . forEach ( ( startBlob , i ) => {
99
96
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
+ )
102
108
103
109
const gradient = ctx . createRadialGradient (
104
- interBlobs [ i ] . x ,
105
- interBlobs [ i ] . y ,
110
+ currentBlobs [ i ] . x ,
111
+ currentBlobs [ i ] . y ,
106
112
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
110
116
)
111
117
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
+ )
118
133
119
134
gradient . addColorStop (
120
135
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)`
122
137
)
123
138
gradient . addColorStop (
124
139
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)`
126
141
)
127
142
128
143
ctx . fillStyle = gradient
129
144
ctx . beginPath ( )
130
145
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 ,
134
149
0 ,
135
150
Math . PI * 2
136
151
)
@@ -141,6 +156,7 @@ export function BackgroundAnimation() {
141
156
rafId = requestAnimationFrame ( animate )
142
157
} else {
143
158
timeout = setTimeout ( ( ) => {
159
+ morphDuration = 4000
144
160
start ( )
145
161
} , waitDuration )
146
162
}
@@ -178,3 +194,24 @@ export function BackgroundAnimation() {
178
194
</ div >
179
195
)
180
196
}
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