Search code examples
reactjsreact-spring

How to properly move a React component from left to right using react-spring on scroll?


I have a div which contains an image and some text on it aligned to center

I need to make a transition with react-spring that when I scroll it should look like the text is coming from -x value to 0 and it has to be very smooth and real looking.

So I looked in to the react-spring documentation and they don't have a rich documentation on these kind of things. Only few examples.

For an example, how can I find other props for a scenario like this?

import {useTransition, animated} from 'react-spring'

const component = () => {

  const props = useSpring({opacity: 1, from: {opacity: 0}}) // how can I know other parameters like opcacity, from, to etc...

  return (
    <animated.div>
      {div contents here}
    </animated.div>
  )
}

And anyone to help me with the left-right transition where text come from left and lands at the center of the above mentioned image WHEN SCROLLING THROUGH?

Thank you.


Solution

  • I think you might be interested in translateX

    from left and lands at the center of the above mentioned image

    Combine the above with display: flex and align-items: center

    Example

    import React, { useState, useEffect } from "react";
    import ReactDOM from "react-dom";
    import { useSpring, animated } from "react-spring";
    
    const style = {
      background: 'url("https://picsum.photos/200/300") center center / cover no-repeat',
      padding: '10px',
      width: '300px',
      height: '200px',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
    }
    
    const textStyle = {
      color: 'white',
      fontSize: '50px',
      background: 'black'
    }
    
    const App = props => {
      const [isLoaded, setLoaded] = useState(false);
      const springProps = useSpring({ 
        opacity: 1, 
        delay: 700,
        reset: isLoaded,
        transform: 'translateX(0px)',
        from: { 
          opacity: 0,
          transform: 'translateX(-250px)'
        } });
    
      useEffect(() => {
        fetch("https://picsum.photos/200/300")
          .then(pr => {
            setLoaded(true);
          })
      }, [])
    
      return <>{isLoaded ? <div style={style}>
            <animated.div style={{...textStyle, ...springProps}}>Some text</animated.div>
          </div> : <span></span>}</>
    };
    

    WHEN SCROLLING THROUGH?

    In this case you would have to use second overload for useSpring, and use destructed set method to update values in onscroll callback

    Example

    const App = props => {
      const [isLoaded, setLoaded] = useState(false);
      const [{ param }, set] = useSpring(() => ({ param: 0 }));
    
      const onScroll = () => {
        let ratio = window.scrollY / window.innerHeight;
        ratio = ratio > 1 ? 1 : ratio;
    
        set({
          param: ratio
        });
      };
    
      useEffect(() => {
        window.addEventListener("scroll", onScroll);
    
        fetch("https://picsum.photos/200/300").then(pr => {
          setLoaded(true);
        });
    
        return () => {
          window.removeEventListener("scroll", onScroll);
        };
      }, []);
    
      return (
        <div style={containerStyle}>
          {isLoaded ? (
            <div style={style}>
              <animated.div
                style={{
                  ...textStyle,
                  opacity: param.interpolate({
                    range: [0, 0.5, 0.75, 1],
                    output: [0, 0.5, 0.75, 1]
                  }),
                  transform: param
                    .interpolate({ range: [0, 0.5, 1], output: [-50, -25, 0] })
                    .interpolate(x => `translateX(${x}px)`)
                }}
              >
                Some text
              </animated.div>
            </div>
          ) : (
            <span />
          )}
        </div>
      );
    };