【问题标题】:nested dynamic height transition effect嵌套动态高度过渡效果
【发布时间】:2021-08-23 01:59:45
【问题描述】:

试图创建一个可重用的折叠组件,但在元素上平滑过渡时出现问题。所以当点击折叠项时,我希望有一个平滑的过渡

这是我迄今为止尝试过的主要部分。

index.js

const Collapse = ({ title, text, child, ...props }) => {
  const [isOpen, setIsOpen] = useState(false);

  const toggleCollapse = () => setIsOpen((isOpen) => !isOpen);
  const closeCollapse = () => setIsOpen(false);

  const content = useRef(null);

  const isParentOpen = props.isParentOpen;

  useEffect(() => {
    if (!isParentOpen) closeCollapse();
  }, [isParentOpen]);

  const height = !isOpen ? "0px" : `auto`; // ${content.current?.scrollHeight}px

  return (
    <CollapseContainer>
      <CollapseButton isOpen={isOpen} onClick={toggleCollapse}>
        <CollapseTitleWrapper>{title}</CollapseTitleWrapper>
      </CollapseButton>
      <CollapseContent ref={content} max_height={height}>
        <CollapseText>
          {text}
          {child?.map((datumn, index) => (
            <Collapse
              {...datumn}
              key={`collapse-child-${index}`}
              isParentOpen={isOpen}
            />
          ))}
        </CollapseText>
      </CollapseContent>
    </CollapseContainer>
  );
};

export default Collapse;

所以我可以使用 ref 动态计算内容的高度,但会发生平滑过渡,但我会在嵌套的子折叠内得到一个滚动,这是我不想要的。有没有办法在 height:auto 上应用过渡。

这是工作的codesandbox

【问题讨论】:

  • 不,您不能像许多 SO 问题所涵盖的那样转换到自动。听起来您需要在需要时关闭溢出。
  • 那么还有其他方法可以实现吗?
  • @Paulie_D 如果我使用 onTransitionEnd 事件,那么在打开手风琴时,我将能够在没有滚动和平滑过渡事件的情况下显示,但是在关闭时它不起作用有没有办法实现这一点
  • 您可以进行平滑过渡,但为此您需要根据 scrollHeight 创建高度。这就是你如何获得动态高度并在高度上编写过渡。
  • 你愿意安装一个 npm 包来解决这个问题吗?我在几个项目中使用过这个:npmjs.com/package/react-animate-height

标签: javascript css reactjs


【解决方案1】:

使用视口单位 -> 100vhhttps://css-tricks.com/fun-viewport-units/

  const height = !isOpen ? "0px" : `100vh`; // ${content.current?.scrollHeight}px

另外,为了隐藏临时滚动条,我将overflow: hidden; 应用到export const CollapseContent = styled.div

您的代码笔已修改:https://codesandbox.io/s/strange-swirles-pebp1

【讨论】:

  • 但是,如果我的内容使用这个 100vh 进行更多嵌套,这是否是正确的解决方案,因为我试图计算嵌套子项的实际高度以便它准确。由于我们正在应用溢出隐藏内容将无法显示吗?在打开折叠时提到的代码框上,它的动画效果不正确,但是在正确关闭其显示时可能是什么原因?
  • @dev - 你能在沙箱中添加一个例子来说明你的意思吗?谢谢
  • @Kiglish, stackoverflow.com/questions/67961600/… 对此有任何想法
  • @Kinglish 我对这个问题有一个疑问stackoverflow.com/questions/70063149/… 如果你能帮助我,那将非常有帮助,非常感谢??
【解决方案2】:

获取元素的高度: Ref.current.getBoundingClientRect().height 在过渡开始的那一刻,添加样式 overflow:hidden 以防止滚动条,然后创建一个函数,在过渡元素上调用 onTransitionEnd 以在过渡完成时重新激活溢出(如果需要)。

【讨论】:

    【解决方案3】:

    不可能使用带有auto 关键字的CSS 动画。一种可能的解决方案是使用height 代替maxHeightoverflow: hidden,并在动画完成时将height 设置为auto。我建议使用 WAAPI(Web Animation API),因为它简化了在 js 中使用动画,并且不会像 css 过渡那样冒泡事件。

    这是一个例子:https://codesandbox.io/s/determined-curran-hsrm9?file=/src/Collapse/index.js

    【讨论】:

    【解决方案4】:

    我认为您应该改变概念,只需使用更优化的 CSS 动画即可实现,并允许您创建自定义效果!

    首先我们定义两个动画(is-open和is-close):

    .is-open {
      animation: is-open 0.3s ease both;
    }
    
    @keyframes is-open {
      from {
        opacity: 0;
        transform: scaleY(0);
      }
      to {
        opacity: 1;
        transform: scaleY(1);
        height: 100%;
      }
    }
    

    .is-closed {
      animation: is-closed 0.3s ease both;
    }
    
    @keyframes is-closed {
      from {
        opacity: 1;
        transform: scaleY(1);
      }
      to {
        opacity: 0;
        transform: scaleY(0);
        height: 0;
      }
    }
    

    现在我们唯一需要的是一个处理这些动画的条件类:

    <CollapseContent
        ref={content}
        className={isOpen ? "is-open" : "is-closed"}
    >
    

    Check the result here.

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多