【问题标题】:how to use a styled component to play an animation on scroll in react如何在反应中使用样式化组件在滚动时播放动画
【发布时间】:2022-01-26 17:17:01
【问题描述】:

我一直在尝试使用样式化组件动画来使导航栏在向下滚动时改变颜色,并在我向上滚动时将其恢复为原始颜色。我目前面临的唯一问题是,我不知道如何仅在向下滚动页面时触发它,并在我再次点击顶部时将其恢复正常。

const ChangeColor = keyframes`
0%{
  background-color: #121314;
}
100%{
    background-color: white;
}
`;

const GeneralContainer = styled.body`
  background-color: #121314;
  height: 10000px;

  margin: 0;
`;

const NavBarContainer = styled.div`
  border: 1px green solid;
  height: 64px;
  position: fixed;
  width: 100%;
  animation: ${NavForward} 1s linear alternate forwards 1; //I just want this to fire once when I scroll downward and fire again when I return to the top of the page.
`;

export default function Home() {
  const [offset, setOffset] = useState(0);
  const [isUpper, setIsUpper] = useState(true); // was trying to use this to trigger but couldnt

  useEffect(() => {
    const onScroll = () => {
      setOffset(window.pageYOffset);
      if (window.pageYOffset > 30 && isUpper === true) {
        setIsUpper(false);
      } else if (window.pageYOffset <= 30 && isUpper === false) {
        setIsUpper(true);
      }
    };
    // clean up code
    window.removeEventListener("scroll", onScroll);
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  return (
    <GeneralContainer>
      <NavBarContainer
        isUpper={isUpper}
        scoll={offset}
      ></NavBarContainer>
    </GeneralContainer>
  );
}

【问题讨论】:

    标签: css reactjs css-animations styled-components


    【解决方案1】:

    我个人不会为此使用动画。添加和删​​除类是一种更简单的方法。

    您想要做的与您已经在做的类似,但基本上设置了另一个效果,以便在 Y 偏移量超过您的任意高度时进行监听。

    首先,设置一个我们将在处理滚动的效果中调用的函数:

    const handleScroll = () => setOffset(window.pageYOffset);
    

    然后创建一个专门的效果来处理滚动:

    useEffect(() => {
      window.addEventListener("scroll", handleScroll);
      return () => {
        window.removeEventListener("scroll", handleScroll);
      };
    }, []);
    

    然后,在另一个效果中,我们将听听是否已经超过了隐藏/显示背景颜色的像素数量:

    useEffect(() => {
      if (offset > 100) {
        setIsUpper(false);
      } else {
        setIsUpper(true);
      }
    }, [offset]);
    

    有了这个,我们需要让样式化的组件知道什么时候发生了变化。使用 css 类对这里的工作有好处:

    <NavBarContainer className={isUpper ? "active" : ""}></NavBarContainer>
    

    然后在您的 NavBarContainer 样式组件中,添加一个确保使用过渡而不是动画的类:

    const NavBarContainer = styled.div`
      // ... the rest of your styles
      transition: 1s ease;
    
      &.active {
        background-color: white;
      }
    `;
    

    所有这些都应该有效。 Check out the sandbox here. 一个工作示例。

    另外,我已将您的GeneralContainer 组件更改为使用div 作为HTML 标记,而不是body 标记。这是因为你的 React 应用被挂载到 div 并且在 body 中嵌套 body 在技术上是无效的 HTML。

    【讨论】:

    • GeneralContainer 是 body 类型,因为我使用的是 nextjs,我需要重写要放置在顶部的导航栏的边距。无论如何,您提供的解决方案非常有效,非常感谢您的帮助。
    【解决方案2】:

    你可以这样做:

    // Get a hook function
    const {
      useState,
      useEffect
    } = React;
    
    const Home = () => {
      const [offset, setOffset] = useState(0);
      const [isUpper, setIsUpper] = useState(true); // was trying to use this to trigger but couldnt
    
      useEffect(() => {
        const onScroll = () => {
          setOffset(window.pageYOffset);
          if (window.pageYOffset > 30) {
            setIsUpper(false);
          } else if (window.pageYOffset <= 30) {
            setIsUpper(true);
          }
        };
        // clean up code
        window.removeEventListener("scroll", onScroll);
        window.addEventListener("scroll", onScroll, {
          passive: true
        });
        return () => window.removeEventListener("scroll", onScroll);
      }, []);
    
      return ( <nav className ={isUpper ? 'top' : ''} > < /nav>
      );
    };
    
    // Render it
    ReactDOM.render( <
      Home / > ,
      document.getElementById("react")
    );
    body {
      height: 2000px;
    }
    
    nav {
      height: 50px;
      position: fixed;
      top: 0;
      width: 100%;
      background-color: red;
      transition: background-color 1s ease;
    }
    
    nav.top {
      background-color: blue;
      transition: background-color 1s ease;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
    <div id="react"></div>

    【讨论】:

      猜你喜欢
      • 2020-05-03
      • 2017-03-14
      • 1970-01-01
      • 2013-08-30
      • 1970-01-01
      • 2017-03-04
      • 2020-05-20
      • 2020-11-09
      • 1970-01-01
      相关资源
      最近更新 更多