Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 1x 15x 3x 3x 15x 15x 15x 15x 1x 1x 1x 1x 10x 10x 10x 10x 10x 10x 10x 10x 10x 10x | /**
* useScrollAnimation Hook
*
* Hook for triggering animations when elements scroll into view
*
* @example
* ```tsx
* function MyComponent() {
* const [ref, controls] = useScrollAnimation();
*
* return (
* <motion.div
* ref={ref}
* animate={controls}
* initial="hidden"
* variants={fadeInUp}
* >
* Content that animates in on scroll
* </motion.div>
* );
* }
* ```
*/
'use client';
import { useEffect, useRef } from 'react';
import { useAnimation, useInView } from 'framer-motion';
interface UseScrollAnimationOptions {
/** Trigger animation once or every time element enters viewport */
once?: boolean;
/** Amount of element that should be visible before triggering (0-1) */
amount?: number;
}
/**
* Hook that triggers animation when element scrolls into view
*/
export function useScrollAnimation(options: UseScrollAnimationOptions = {}) {
const { once = true, amount = 0.2 } = options;
const ref = useRef<HTMLElement>(null);
const controls = useAnimation();
const isInView = useInView(ref, {
once,
amount});
useEffect(() => {
if (isInView) {
controls.start('animate');
} else if (!once) {
controls.start('initial');
}
}, [isInView, controls, once]);
return [ref, controls] as const;
}
/**
* Hook that returns whether element is currently in view
*/
export function useIsInView(options: UseScrollAnimationOptions = {}) {
const { once = false, amount = 0.2 } = options;
const ref = useRef<HTMLElement>(null);
const isInView = useInView(ref, {
once,
amount});
return [ref, isInView] as const;
}
|