【问题标题】:I want the arrow icon to flip up and down every time the state changes.and I want to animate it我希望箭头图标在每次状态更改时上下翻转。我想为它设置动画
【发布时间】:2021-12-07 22:01:51
【问题描述】:

我正在使用 react、styled-components。
当 state(visible) 设置为 true 时,会显示 DropMenu box1 和 box2。
我们希望 ArrowDown 图标在状态为真时向上翻转,在状态为假时向下翻转。
我还想在翻转时应用动画。
我想在以下站点中添加类似 Dropdown 的动画。

Reference site

code

import "./styles.css";
import styled from "styled-components";
import React, { useState, useCallback } from "react";
import { ArrowDown } from "./ArrowDown";

const Item = styled.div<{ active?: boolean }>`
  height: 40px;
  width: 300px;
  padding: 0px 30px;

  &:hover {
    background: #fafbfb;
  }
`;

const DropMenu = styled.div`
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: #899098;
  width: 100%;
  height: 100%;
  font-size: 14px;
  font-weight: bold;
  gap: 12px;
  :hover {
    color: gray;
  }
  div {
    display: flex;
    align-items: center;
    gap: 12px;
  }
`;

const DropText = styled.div`
  padding-left: 32px;
`;

export const App = () => {
  const [visible, setVisible] = useState(false);
  const handleDropVisibleChange = useCallback(() => {
    setVisible((prevVisible) => !prevVisible);
  }, [visible]);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <Item onClick={handleDropVisibleChange}>
        <DropMenu>
          <div>
            <span>Menu</span>
          </div>
          <ArrowDown />
        </DropMenu>
      </Item>
      {visible && (
        <div style={{ transition: "all 0.5s ease" }}>
          <Item>
            <DropMenu>
              <DropText>box1</DropText>
            </DropMenu>
          </Item>
          <Item>
            <DropMenu>
              <DropText>box2</DropText>
            </DropMenu>
          </Item>
        </div>
      )}
    </div>
  );
};

export default App;

【问题讨论】:

    标签: reactjs styled-components


    【解决方案1】:

    TLDR

    1. 将您的 MenuItem 组件变形器更改为类似
    const DropMenuWrapper = styled.div<{ visible: boolean }>`
      transition: all 0.5s ease;
      opacity: ${(props) => (props.visible ? 1 : 0)};
    `;
    
    1. 用以下替换可见性开关机制
    - {visible && (
    -     <div style={{ transition: "all 0.5s ease" }}>
    
    +     <DropMenuWrapper visible={visible}>
    

    类似的动作也可以添加到向下箭头图标的样式 (ArrowDown SVG图标如果是自定义编写的组件,必须接受样式)

    <ArrowDown
      style={{
        transition: "all 0.5s ease",
        transform: `rotate(${visible ? 0 : "0.5turn"})`
      }}
    />
    

    为什么会这样:

    当一个组件(子组件/元素)被挂载到 react 中时,它会开始一个完整的生命周期,朝向browser paint。 所以它必须具有导致元素动画的属性,例如,我将不透明度过渡添加到示例本身,强制它在第一眼看到动画并消失。

    虽然它会带来一些性能成本,即在 dom 中仍然存在看不见的元素(但不可见),这也使其不利于可访问性,但这是实现此行为的最简单方法。

    考虑这个例子如果你有一个动画元素,如果你刷新浏览器,它是否会显示动画,如果答案是肯定的,它也会在反应中显示动画。

    在 react 中做一些动画的另一种方式。

    在这种情况下,您还可以触发结束事件并在动画消失并完全结束时开始卸载组件。

    如果您想了解在组件被卸载并从 aka dom 中移除时转换所需的内容,我强烈建议您阅读 svelte docuementation 的动画部分

    【讨论】:

    • Type '{ style: { transition: string;变换:字符串; }; }' 不可分配给类型“IntrinsicAttributes”。类型“IntrinsicAttributes”.ts(2322 上不存在属性“样式”)
    • 出现上述错误,没有应用动画
    • 我将它封装在一个 span 标签中,它起作用了。
    • const Rotate = styled.span` transition: "all 0.5s ease";变换: ${({ 可见 }) => (可见 ? "rotate(0)" : "rotate(0.5turn)")}; `;
    • 使用 styled-components 时动画应用不正确
    【解决方案2】:

    我所做的,对于更高级的开发人员来说可能看起来很愚蠢的是实现一个简单的检查来切换图标。

    注意:不过,这没有动画。这只是一个简单的switcharoo

    1. 在组件中定义状态 const [isOpen, setIsOpen] = useState(false);

    2. 检查图标是打开还是关闭,如果打开,ExpandLessIcon,如果关闭,ExpandMoreIcon。

            <ExpandLessIcon
              onClick={() => {
                setIsOpen(!isOpen);
              }}
            />
          ) : (
            <ExpandMoreIcon
              onClick={() => {
                setIsOpen(!isOpen);
              }}
            />
          )}
    
    
    1. 它的工作方式是,一旦点击,它就会一遍又一遍地翻转真假状态,这反过来又会改变图标。

    【讨论】:

      猜你喜欢
      • 2020-01-19
      • 1970-01-01
      • 2019-04-18
      • 2017-05-19
      • 2017-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多