UNPKG

@gatsby-mdx-suite/mdx-scroll-effects

Version:
101 lines (85 loc) 2.78 kB
import React, { useState, useMemo, useCallback } from 'react' import propTypes from 'prop-types' import { gsap } from 'gsap' import { ScrollTrigger } from 'gsap/ScrollTrigger' import { useBreakpoint } from '@gatsby-mdx-suite/helpers/hooks/use-breakpoint' import { killScrollTrigger, useKillScrollTriggerOnCleanup, } from '@gatsby-mdx-suite/helpers/styling/gsap' gsap.registerPlugin(ScrollTrigger) const Parallax = ({ children, till, from, speed, markers, ...props }) => { const activeBreakpoints = useBreakpoint() const [scrollTriggerInstance, setScrollTriggerInstance] = useState(null) useKillScrollTriggerOnCleanup(scrollTriggerInstance) // Activate effect based on props const effectActive = useMemo(() => { if ( (!till && !from) || (till && !activeBreakpoints[till]) || (from && activeBreakpoints[from]) ) { return true } killScrollTrigger(scrollTriggerInstance) return false }, [till, from, activeBreakpoints, scrollTriggerInstance]) // Calculate css transform values based on effect state const [transformStart, transformEnd] = useMemo( () => [ effectActive ? `translateY(${speed})` : '', effectActive ? `translateY(-${speed})` : '', ], [speed, effectActive] ) // Initialize ScrollTrigger on child mount const initScrollTrigger = useCallback( (node) => { if (!node || !effectActive) { return } const positionParent = node.closest('section,#___gatsby') const gsapInstance = gsap .timeline({ scrollTrigger: { trigger: positionParent, scrub: true, markers, start: `top center`, end: `bottom center`, invalidateOnRefresh: true, }, }) .to(node, { transform: transformEnd, }) setScrollTriggerInstance(gsapInstance) }, [effectActive, transformEnd, markers] ) return ( <div {...props} ref={initScrollTrigger} style={{ transform: transformStart }} > {children} </div> ) } Parallax.defaultProps = { speed: '50%', markers: false, } Parallax.propTypes = { children: propTypes.node.isRequired, /** Speed of the component while traveling parallax on the Y-axis. Usually a value between 25% and 100% */ speed: propTypes.string, /** Add the debug attribute to render markers to debug the parallax animation */ markers: propTypes.bool, /** Enable parallax scrolling of the component till given screen size is reached */ till: propTypes.oneOf(['sm', 'md', 'lg', 'xl']), /** Enable parallax scrolling of the component as soon given screen size is reached */ from: propTypes.oneOf(['sm', 'md', 'lg', 'xl']), } export default Parallax