@erosnicolau/animated-text
Version:
Advanced React animated text component with comprehensive animation effects
54 lines (53 loc) • 2.27 kB
JavaScript
import { useEffect, useRef, useState } from 'react';
export const useVirtualizedIntersectionObserver = (options = {}) => {
const [isIntersecting, setIsIntersecting] = useState(false);
const [isInViewport, setIsInViewport] = useState(true); // For virtualization
const elementRef = useRef(null);
const { enableVirtualization = false, virtualizationMargin = '100px', onVirtualize, ...intersectionOptions } = options;
// Normalize virtualization margin to ensure valid CSS format
const normalizedMargin = virtualizationMargin.includes('px') || virtualizationMargin.includes('%')
? virtualizationMargin
: `${virtualizationMargin}px`;
useEffect(() => {
const element = elementRef.current;
if (!element)
return;
// Animation trigger observer (existing behavior)
const animationObserver = new IntersectionObserver(([entry]) => {
if (entry && entry.isIntersecting) {
setIsIntersecting(true);
// Once triggered, disconnect to prevent re-triggering
animationObserver.disconnect();
}
}, {
threshold: 0.1,
rootMargin: '0px 0px -100px 0px',
...intersectionOptions
});
// Virtualization observer (new optimization)
let virtualizationObserver = null;
if (enableVirtualization) {
virtualizationObserver = new IntersectionObserver(([entry]) => {
if (entry) {
const isVisible = entry.isIntersecting;
setIsInViewport(isVisible);
onVirtualize?.(isVisible);
}
}, {
threshold: 0,
rootMargin: normalizedMargin // Properly formatted margin
});
virtualizationObserver.observe(element);
}
animationObserver.observe(element);
return () => {
animationObserver.disconnect();
virtualizationObserver?.disconnect();
};
}, [enableVirtualization, normalizedMargin, onVirtualize, intersectionOptions]);
return {
elementRef,
isIntersecting,
isInViewport: enableVirtualization ? isInViewport : true
};
};