1

I'm attempting to create an animation in which one element fades based upon the scroll position of another. I was able to get the scrolling element to work using React Spring, but I'm struggling to wrap my head around how to leverage state hooks without conditionals and only being able to set state at a component top level.

SandBox

const HomeView = () => {
  const ref = useRef();
  const [isVisible, setVisible] = useState(true);
  const [{ offset }, set] = useSpring(() => ({ offset: 0 }));

  const calc = (o) => {
    if (o < 1004) {
      return `translateY(${o * 0.08}vh)`;
    } else {
      // this won't work b/c im trying to useState in a Fn
      setVisible(false);
      return `translateY(${1012 * 0.08}vh)`;
    }
  };

  const handleScroll = () => {
    const posY = ref.current.getBoundingClientRect().top;

    const offset = window.pageYOffset - posY;
    set({ offset });
  };

  useEffect(() => {
    window.addEventListener("scroll", handleScroll);

    return () => {
      window.removeEventListener("scroll", handleScroll);
    };
  });

  return (
    <div ref={ref} className="home-view" style={homeViewStyles}>
      <div style={topSectionStyles} className="top-content-container"></div>
      <animated.div
        className="well-anim"
        style={{
          width: "100vw",
          height: "500px",
          transform: offset.interpolate(calc),
          zIndex: 300,
          top: "340px",
          position: "absolute"
        }}
      >
        <h1>Well,</h1>
      </animated.div>
      {/* Trying to fade this component when above animated.div is right above it */}
      <h2 style={{ paddingTop: "90px" }} fade={isVisible}>
        Hello There!
      </h2>
      {/***************************************/}
    </div>
  );
};
Tim Fischer
  • 15
  • 1
  • 4

1 Answers1

0

You are almost there. I think the problem here is with the fade attribute. The setVisible function is invoked all right. I would introduce a second spring to deal with the opacity with the h2 element, based on the state of the isVisible variable.

const {opacity} = useSpring({opacity: isVisible ? 1 : 0});
  <animated.h2 style={{ paddingTop: "90px", opacity }} >
    Hello There!
  </animated.h2>

https://codesandbox.io/s/wild-dew-tyynk?file=/src/App.js

Peter Ambruzs
  • 7,763
  • 3
  • 30
  • 36