UNPKG

framer-motion

Version:

A simple and powerful React animation library

59 lines (56 loc) 2.13 kB
import { useConstant } from '../../utils/use-constant.mjs'; import { createScrollUpdater, createScrollMotionValues } from './utils.mjs'; import { addDomEvent } from '../../events/use-dom-event.mjs'; import { useIsomorphicLayoutEffect } from '../../utils/use-isomorphic-effect.mjs'; import { invariant } from 'hey-listen'; var getElementScrollOffsets = function (element) { return function () { return { xOffset: element.scrollLeft, yOffset: element.scrollTop, xMaxOffset: element.scrollWidth - element.offsetWidth, yMaxOffset: element.scrollHeight - element.offsetHeight, }; }; }; /** * Returns MotionValues that update when the provided element scrolls: * * - `scrollX` — Horizontal scroll distance in pixels. * - `scrollY` — Vertical scroll distance in pixels. * - `scrollXProgress` — Horizontal scroll progress between `0` and `1`. * - `scrollYProgress` — Vertical scroll progress between `0` and `1`. * * This element must be set to `overflow: scroll` on either or both axes to report scroll offset. * * ```jsx * export const MyComponent = () => { * const ref = useRef() * const { scrollYProgress } = useElementScroll(ref) * * return ( * <div ref={ref}> * <motion.div style={{ scaleX: scrollYProgress }} /> * </div> * ) * } * ``` * * @public */ function useElementScroll(ref) { var values = useConstant(createScrollMotionValues); useIsomorphicLayoutEffect(function () { var element = ref.current; invariant(!!element, "ref provided to useScroll must be passed into a HTML element."); if (!element) return; var updateScrollValues = createScrollUpdater(values, getElementScrollOffsets(element)); var scrollListener = addDomEvent(element, "scroll", updateScrollValues, { passive: true }); var resizeListener = addDomEvent(element, "resize", updateScrollValues); return function () { scrollListener && scrollListener(); resizeListener && resizeListener(); }; }, []); return values; } export { useElementScroll };