繁体   English   中英

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

[英]How to use transition effect on accordion

我使用 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;
`;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM