微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在手风琴上使用过渡效果

如何解决如何在手风琴上使用过渡效果

我使用React和样式化的组件创建了简单的手风琴。我在制作效果时遇到问题,以便下部可以缓慢滑出而不会立即弹出。我使用了过渡,但我不知道为什么在我的情况下它不起作用。我的代码有一部分:https://codesandbox.io/s/sweet-blackwell-v78wt?file=/src/App.js

解决方法

为获得最佳效果,您需要将max-height0px转换为内容的高度,反之亦然。您需要使用useRefuseEffect钩子来选择元素并手动设置其样式。

您还需要一个知道内容高度的内部包装器。这将是在折叠容器上设置max-height的参考。

使用onTransitionEnd事件侦听器,您可以在展开手风琴时删除max-height属性。这样一来,元素便可以根据内容进行响应式调整大小。

内容的高度由getBoundingClientRect()函数确定。它返回具有元素的高度,宽度(及更多)的对象。这样,您可以确定内容容器的高度。

下面的示例是一个基于您的代码的可行示例。

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

const Accordion = () => {
  const [isExpanded,setIsExpanded] = useState(false);
  const [isAnimating,setIsAnimating] = useState(false);
  const collapseRef = useRef(null);
  const contentRef = useRef(null);

  const handleClick = () => {
    /**
     * isAnimating prevents the accordion from changing
     * state when it is in the middle of a transition.
     */
    if (!isAnimating) {
      setIsAnimating(true);
      setIsExpanded((isExpanded) => !isExpanded);
    }
  };

  const handleTransition = () => {
    if (isExpanded) {
      /**
       * Removing the max-height when expanded makes sure
       * that the element still resizes responsively correct.
       */
      collapseRef.current.style.maxHeight = "";
    }
    setIsAnimating(false);
  };

  useEffect(() => {
    const { height } = contentRef.current.getBoundingClientRect();
    collapseRef.current.style.maxHeight = `${height}px`;
    if (!isExpanded) {
      /**
       * This makes sure that the element first is expanded
       * and in the next frame paint is transitioned to 0px.
       * Otherwise the 0px height would overwrite to dynamic height
       * and there'd be no transition.
       */
      requestAnimationFrame(() => {
        collapseRef.current.style.maxHeight = "0px";
      });
    }
  },[isExpanded]);

  return (
    <ContentWrapper onClick={handleClick}>
      <TitleCard>
        <h2>Example text</h2>
      </TitleCard>
      <DescriptionCard
        ref={collapseRef}
        isVisible={isExpanded}
        style={{ maxHeight: "0px" }}
        onTransitionEnd={handleTransition}
      >
        <DescriptionContent ref={contentRef}>
          <p>Example text 2</p>
          <p>Now it expands based on the height of the</p>
          <h3>content.</h3>
          <p>Now it expands based on the height of the</p>
          <h3>content.</h3>
        </DescriptionContent>
      </DescriptionCard>
    </ContentWrapper>
  );
};

export default function App() {
  return (
    <div className="App">
      <Accordion />
    </div>
  );
}

const DescriptionContent = styled.div`
  display: flex;
  flex-direction: column;
`;

const DescriptionCard = styled.div`
  background: grey;
  overflow: hidden;
  align-items: center;
  justify-content: flex-start;
  transition: max-height 0.35s;
`;

const TitleCard = styled.div`
  cursor: pointer;
  height: 4.8rem;
  background: #ffffff;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 1.5em;
`;

const ContentWrapper = styled.div`
  border-radius: 16px;
  border: 2px solid black;
  overflow: hidden;
`;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。