@@ -195,6 +195,21 @@ function createUniforms(width: number, height: number) {
195
195
} ;
196
196
}
197
197
198
+ function createRenderer ( canvas : HTMLCanvasElement , width : number , height : number , dpr = 2 ) {
199
+ return new Renderer ( {
200
+ alpha : true ,
201
+ antialias : true ,
202
+ canvas,
203
+ depth : false ,
204
+ dpr,
205
+ height,
206
+ powerPreference : "high-performance" ,
207
+ premultipliedAlpha : true ,
208
+ webgl : 2 ,
209
+ width,
210
+ } ) ;
211
+ }
212
+
198
213
export type EffectLayerProps = PropsWithChildren < {
199
214
className ?: string ;
200
215
} > ;
@@ -203,6 +218,7 @@ export function EffectLayer({ children, className }: EffectLayerProps) {
203
218
const rRaf = useRef < number > ( null ) ;
204
219
const rRoot = useRef < HTMLDivElement > ( null ) ;
205
220
const rCanvas = useRef < HTMLCanvasElement > ( null ) ;
221
+ const isActive = useRef < boolean > ( false ) ;
206
222
207
223
useEffect ( ( ) => {
208
224
if ( rRoot . current == null ) return ;
@@ -212,18 +228,7 @@ export function EffectLayer({ children, className }: EffectLayerProps) {
212
228
const canvas = rCanvas . current ;
213
229
const rect = root . getBoundingClientRect ( ) ;
214
230
const uniforms = createUniforms ( rect . width , rect . height ) ;
215
- const renderer = new Renderer ( {
216
- alpha : true ,
217
- antialias : false ,
218
- canvas,
219
- depth : false ,
220
- dpr : window . devicePixelRatio ,
221
- height : rect . height ,
222
- powerPreference : "high-performance" ,
223
- premultipliedAlpha : true ,
224
- webgl : 2 ,
225
- width : rect . width ,
226
- } ) ;
231
+ const renderer = createRenderer ( canvas , rect . width , rect . height , window . devicePixelRatio ) ;
227
232
228
233
const { gl } = renderer ;
229
234
const geometry = new Triangle ( gl ) ;
@@ -236,27 +241,34 @@ export function EffectLayer({ children, className }: EffectLayerProps) {
236
241
const mesh = new Mesh ( gl , { geometry, program } ) ;
237
242
238
243
function update ( time : number ) {
244
+ if ( ! isActive . current ) return ;
239
245
uniforms . uTime . value = time * 0.001 ;
240
246
renderer . render ( { scene : mesh } ) ;
241
247
rRaf . current = requestAnimationFrame ( update ) ;
242
248
}
243
249
250
+ function resize ( rect : DOMRect ) {
251
+ if ( ! isActive . current ) return ;
252
+ uniforms . uResolution . value . set ( rect . width , rect . height ) ;
253
+ renderer . setSize ( rect . width , rect . height ) ;
254
+ renderer . render ( { scene : mesh } ) ;
255
+ }
256
+
244
257
const ro = new ResizeObserver ( ( entries ) => {
245
- for ( const entry of entries ) {
246
- if ( entry . target !== root ) continue ;
247
- const rect = entry . contentRect ;
248
- uniforms . uResolution . value . set ( rect . width , rect . height ) ;
249
- renderer . setSize ( rect . width , rect . height ) ;
250
- renderer . render ( { scene : mesh } ) ;
251
- return ;
252
- }
258
+ if ( ! isActive . current ) return ;
259
+ if ( entries . length == null ) return ;
260
+ requestAnimationFrame ( ( ) => {
261
+ resize ( root . getBoundingClientRect ( ) ) ;
262
+ } ) ;
253
263
} ) ;
254
264
255
265
ro . observe ( root ) ;
256
266
rRaf . current = requestAnimationFrame ( update ) ;
257
267
canvas . style . opacity = "1" ;
268
+ isActive . current = true ;
258
269
259
270
return ( ) => {
271
+ isActive . current = false ;
260
272
canvas . style . opacity = "0" ;
261
273
if ( rRaf . current != null ) cancelAnimationFrame ( rRaf . current ) ;
262
274
ro . disconnect ( ) ;
@@ -296,5 +308,6 @@ const styles = {
296
308
"transition-opacity" ,
297
309
"duration" ,
298
310
"ease-[ease-in-out]" ,
311
+ "pointer-events-none" ,
299
312
) ,
300
313
} ;
0 commit comments