perf: optimized gradientblinds
This commit is contained in:
@@ -28,6 +28,7 @@ vi.mock('ogl', () => {
|
|||||||
Triangle: class {
|
Triangle: class {
|
||||||
remove() { }
|
remove() { }
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -41,6 +42,8 @@ globalThis.ResizeObserver = class ResizeObserver {
|
|||||||
describe('GradientBlinds', () => {
|
describe('GradientBlinds', () => {
|
||||||
let rafSpy: any;
|
let rafSpy: any;
|
||||||
let cancelRafSpy: any;
|
let cancelRafSpy: any;
|
||||||
|
let addEventListenerSpy: any;
|
||||||
|
let removeEventListenerSpy: any;
|
||||||
let ioCallback: (entries: IntersectionObserverEntry[]) => void;
|
let ioCallback: (entries: IntersectionObserverEntry[]) => void;
|
||||||
let observeSpy: any;
|
let observeSpy: any;
|
||||||
let disconnectSpy: any;
|
let disconnectSpy: any;
|
||||||
@@ -51,6 +54,8 @@ describe('GradientBlinds', () => {
|
|||||||
});
|
});
|
||||||
cancelRafSpy = vi.spyOn(window, 'cancelAnimationFrame').mockImplementation((_id: number) => {
|
cancelRafSpy = vi.spyOn(window, 'cancelAnimationFrame').mockImplementation((_id: number) => {
|
||||||
});
|
});
|
||||||
|
addEventListenerSpy = vi.spyOn(window, 'addEventListener');
|
||||||
|
removeEventListenerSpy = vi.spyOn(window, 'removeEventListener');
|
||||||
|
|
||||||
// Mock IntersectionObserver
|
// Mock IntersectionObserver
|
||||||
observeSpy = vi.fn();
|
observeSpy = vi.fn();
|
||||||
@@ -133,6 +138,44 @@ describe('GradientBlinds', () => {
|
|||||||
expect(disconnectSpy).toHaveBeenCalled();
|
expect(disconnectSpy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('toggles pointer event listener based on visibility', () => {
|
||||||
|
const { unmount } = render(<GradientBlinds />);
|
||||||
|
|
||||||
|
// Should not listen initially (not visible)
|
||||||
|
// Initially not called
|
||||||
|
expect(addEventListenerSpy).not.toHaveBeenCalledWith('pointermove', expect.any(Function));
|
||||||
|
|
||||||
|
// Simulate on-screen
|
||||||
|
act(() => {
|
||||||
|
if (ioCallback) {
|
||||||
|
ioCallback([{ isIntersecting: true } as IntersectionObserverEntry]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(addEventListenerSpy).toHaveBeenCalledWith('pointermove', expect.any(Function));
|
||||||
|
|
||||||
|
// Reset
|
||||||
|
addEventListenerSpy.mockClear();
|
||||||
|
removeEventListenerSpy.mockClear();
|
||||||
|
|
||||||
|
// Simulate off-screen
|
||||||
|
act(() => {
|
||||||
|
if (ioCallback) {
|
||||||
|
ioCallback([{ isIntersecting: false } as IntersectionObserverEntry]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(removeEventListenerSpy).toHaveBeenCalledWith('pointermove', expect.any(Function));
|
||||||
|
|
||||||
|
// Simulate on-screen again
|
||||||
|
act(() => {
|
||||||
|
if (ioCallback) {
|
||||||
|
ioCallback([{ isIntersecting: true } as IntersectionObserverEntry]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(addEventListenerSpy).toHaveBeenCalledWith('pointermove', expect.any(Function));
|
||||||
|
|
||||||
|
unmount();
|
||||||
|
expect(removeEventListenerSpy).toHaveBeenCalledWith('pointermove', expect.any(Function));
|
||||||
|
});
|
||||||
it('minimizes getBoundingClientRect calls during pointer move', () => {
|
it('minimizes getBoundingClientRect calls during pointer move', () => {
|
||||||
const { unmount } = render(<GradientBlinds />);
|
const { unmount } = render(<GradientBlinds />);
|
||||||
|
|
||||||
@@ -155,8 +198,7 @@ describe('GradientBlinds', () => {
|
|||||||
window.dispatchEvent(event);
|
window.dispatchEvent(event);
|
||||||
});
|
});
|
||||||
|
|
||||||
// EXPECTATION: It should NOT be called.
|
// EXPECTATION: It should NOT be called because the listener shouldn't be attached (not visible)
|
||||||
// This will fail currently.
|
|
||||||
expect(spy).not.toHaveBeenCalled();
|
expect(spy).not.toHaveBeenCalled();
|
||||||
|
|
||||||
unmount();
|
unmount();
|
||||||
|
|||||||
@@ -330,7 +330,6 @@ void main() {
|
|||||||
uniforms.iMouse.value = [x, y];
|
uniforms.iMouse.value = [x, y];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
window.addEventListener('pointermove', onPointerMove);
|
|
||||||
|
|
||||||
const loop = (t: number) => {
|
const loop = (t: number) => {
|
||||||
rafRef.current = requestAnimationFrame(loop);
|
rafRef.current = requestAnimationFrame(loop);
|
||||||
@@ -364,11 +363,13 @@ void main() {
|
|||||||
lastTimeRef.current = 0;
|
lastTimeRef.current = 0;
|
||||||
rafRef.current = requestAnimationFrame(loop);
|
rafRef.current = requestAnimationFrame(loop);
|
||||||
}
|
}
|
||||||
|
window.addEventListener('pointermove', onPointerMove);
|
||||||
} else {
|
} else {
|
||||||
if (rafRef.current) {
|
if (rafRef.current) {
|
||||||
cancelAnimationFrame(rafRef.current);
|
cancelAnimationFrame(rafRef.current);
|
||||||
rafRef.current = null;
|
rafRef.current = null;
|
||||||
}
|
}
|
||||||
|
window.removeEventListener('pointermove', onPointerMove);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
observer.observe(container);
|
observer.observe(container);
|
||||||
|
|||||||
Reference in New Issue
Block a user