【问题标题】:React: Stop a styled-components animation from running when the component is first mountedReact:在组件首次安装时停止运行样式化组件动画
【发布时间】:2020-10-08 21:07:20
【问题描述】:

我有一个styled-component,它接收道具以确定要使用的动画。这是控制一个箭头图标,当活动时旋转“打开”,非活动时保持“关闭”。

这是styled-component 和两个keyframes 动画的样子:

const rotate_down = keyframes`
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(90deg);
  }
`;

const rotate_up = keyframes`
  from {
    transform: rotate(90deg);
  }
  to {
    transform: rotate(0deg);
  }
`;

const OpenUserSettings = styled.div`
  cursor: pointer;
  width: 20px;
  height: 20px;
  transition: 0.3s;
  animation: ${props => (props.rotate ? rotate_down : rotate_up)} 0.5s ease
    forwards;
  margin-top: 2px;
  box-sizing: border-box;
  display: flex;
  justify-content: center;
  align-items: center;

  & > img {
    width: 5px;
  }
`

传入的 rotate 属性是一个布尔值,通过 React 组件中的 onClick 处理程序进行切换:

    <OpenUserSettings
      rotate={arrowDown}
      onClick={() => {
        this.setState(prevState => ({
          arrowDown: !prevState.arrowDown
        }));
      }}
    >
      <img src={OpenArrow} alt="menu drop down arrow" />
    </OpenUserSettings>

这有效,当点击箭头时,rotate 属性被传递到 OpenUserSettings 并成功在 rotate_uprotate_down keyframes 之间切换。

现在我的问题是,当 React 组件首次挂载时,arrowDown 默认设置为 false,这意味着 rotate 属性将为 false。这会导致styled-component 在第一次安装时将动画设置为rotate_up。我认为这很难想象,所以看看这个看看我在描述什么:

当页面刷新时,您可以看到rotate_up 动画正在快速触发。我需要箭头保持关闭状态,但我不需要 rotate_up 动画在第一次加载以关闭它时触发。这是像react-transition-group 这样的情况,我可以控制初始输入,还是可以用逻辑处理?

【问题讨论】:

    标签: javascript css reactjs styled-components


    【解决方案1】:

    我对堆栈溢出的第一个贡献,多么令人兴奋!

    为确保动画不会在安装时呈现,请将您的状态初始化为真/假,我记得最初将我的状态设置为 null。

    在您的样式化组件中,您可以将 null / true / false 作为 prop 传递,并在组件外部定义一个函数,该函数对 null / true / false 执行检查。 (我用的是 TypeScript,所以不要复制类型)

    function showAnimationOrNot(status: boolean | null) {
      if (status === true) {
        return `animation: nameAnimationIn 1s ease forwards;`
      } else if (status === false) {
        return `animation: nameAnimationOut 1s ease-out forwards;`
      } else if (status === null) {
        return ""
      }
    }
    

    在您的样式化组件中只需添加一行:

    ${(props: PropsDisplay) => show(props.show)};
    

    我就是这样做的,我相信还有更优雅的方法,但它确实做到了在安装时预先制作动画。

    作为回报,如果有人知道如何在函数的返回中突出显示样式化的组件语法,就像我在这里使用的那样(来自上面的示例):

    return `animation: comeout 1s ease-out forwards;`
    

    请告诉我!寻找那个!谢谢你,祝你好运!

    继续制作动画! :)

    【讨论】:

      【解决方案2】:

      我认为在这里使用 CSS transform/transition 会比 animation 更轻松。代码如下:

      const rotateDeg = props.rotate ? '90deg' : '0deg';
      
      const OpenUserSettings = styled.div`
        cursor: pointer;
        width: 20px;
        height: 20px;
        transition: all 0.3s ease;
        transform: rotate(${rotateDeg});
        margin-top: 2px;
        box-sizing: border-box;
        display: flex;
        justify-content: center;
        align-items: center;
      
        & > img {
          width: 5px;
        }
      `
      

      我不太明白你想要箭头在哪个位置,所以你可能需要翻牌 0deg90deg,我认为它实际上可能是 -90deg,但希望这会有所帮助。

      编辑

      您的问题实际上是如何停止动画。您可以使用 animation-play-state 暂停 CSS 动画。在这种情况下,您可以使用animation-play-state: paused; 安装组件,然后添加一个额外的道具以在第一次单击时将其更改为running,但这似乎不必要地复杂IMO。

      More on animation-play-state.

      【讨论】:

        猜你喜欢
        • 2017-03-14
        • 1970-01-01
        • 2021-04-13
        • 1970-01-01
        • 2020-09-26
        • 1970-01-01
        • 2022-06-19
        • 2021-09-02
        • 2020-08-22
        相关资源
        最近更新 更多