Framer Motion이 포함된 애니메이션 모달

Framer Motion은 React 애플리케이션에 선언적 애니메이션을 추가하기 위한 React 라이브러리입니다. 애니메이션 슈퍼 파워로 확장하기 위해 일반 HTML 요소를 래핑하는 다양한 구성 요소를 제공합니다.

다양한 애니메이션 스타일로 Framer Motion으로 모달을 만들고 싶습니다.

설정



React 애플리케이션에 Framer 모션 패키지 설치

npm i framer-motion



애니메이션 모달



트리거 버튼



클릭하면 모달이 열리는 버튼을 만듭니다. 열기/닫기 상태를 추적하기 위해 stateful 값modalOpen을 정의합니다. 이 예에서는 motion.div 구성 요소를 사용하여 버튼 자체에도 애니메이션을 적용합니다.

function App() {
  const [modalOpen, setModalOpen] = useState(false);

  const close = () => setModalOpen(false);
  const open = () => setModalOpen(true);

  return (
    <div>
      <motion.button
        whileHover={{ scale: 1.1 }}
        whileTap={{ scale: 0.9 }}
        className="save-button"
        onClick={() => (modalOpen ? close() : open())}
      >
        Launch modal
      </motion.button>
    </div>
  )
}


배경



모달의 배경으로 사용할 구성 요소를 만듭니다. 이 구성 요소는 페이드 인 및 페이드 아웃되는 motion.div 구성 요소입니다. 배경을 클릭할 때 모달을 닫으려면 onClick 소품이 필요합니다.

import { motion } from "framer-motion";

const Backdrop = ({ children, onClick }) => {

  return (
    <motion.div
      onClick={onClick}
      className="backdrop"
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
    >
      {children}
    </motion.div>
  );
};

export default Backdrop;


모달 창



모달 구성 요소는 Backdrop을 사용한 다음 애니메이션이 들어오고 나가는 자체 구성 요소motion.div를 가집니다. 애니메이션 상태는 dropIn 객체에 정의되어 있습니다. Framer는 DOM에 마운트될 때 한 상태에서 다른 상태로 전환됩니다.

또한 모달을 클릭할 때 stopPropagation가 어떻게 호출되는지 확인하십시오. 이렇게 하면 모달을 클릭할 때 닫히지 않습니다.

import { motion } from "framer-motion";
import Backdrop from "../Backdrop";

const dropIn = {
    hidden: {
      y: "-100vh",
      opacity: 0,
    },
    visible: {
      y: "0",
      opacity: 1,
      transition: {
        duration: 0.1,
        type: "spring",
        damping: 25,
        stiffness: 500,
      },
    },
    exit: {
      y: "100vh",
      opacity: 0,
    },
  };


const Modal = ({ handleClose, text }) => {

    return (
      <Backdrop onClick={handleClose}>
          <motion.div
            onClick={(e) => e.stopPropagation()}  
            className="modal orange-gradient"
            variants={dropIn}
            initial="hidden"
            animate="visible"
            exit="exit"
          >
            <p>{text}</p>
            <button onClick={handleClose}>Close</button>
          </motion.div>
      </Backdrop>
    );
  };


export default Modal;


현재 상태 애니메이션



Framer Motion에는 DOM에서 추가/제거되는 구성 요소에 대한 애니메이션을 처리할 수 있는 AnimatePresence 구성 요소가 내장되어 있습니다. 모달 구성 요소 제거를 애니메이션화하려면 필요합니다.

<AnimatePresence
    // Disable any initial animations on children that
    // are present when the component is first rendered
    initial={false}
    // Only render one component at a time.
    // The exiting component will finish its exit
    // animation before entering component is rendered
    exitBeforeEnter={true}
    // Fires when all exiting nodes have completed animating out
    onExitComplete={() => null}
>
    {modalOpen && <Modal modalOpen={modalOpen} handleClose={close} />}
</AnimatePresence>


추가 애니메이션



튀기다




const flip = {
  hidden: {
    transform: "scale(0) rotateX(-360deg)",
    opacity: 0,
    transition: {
      delay: 0.3,
    },
  },
  visible: {
    transform: " scale(1) rotateX(0deg)",
    opacity: 1,
    transition: {
      duration: 0.5,
    },
  },
  exit: {
    transform: "scale(0) rotateX(360deg)",
    opacity: 0,
    transition: {
      duration: 0.5,
    },
  },
};


신문




const newspaper = {
  hidden: {
    transform: "scale(0) rotate(720deg)",
    opacity: 0,
    transition: {
      delay: 0.3,
    },
  },
  visible: {
    transform: " scale(1) rotate(0deg)",
    opacity: 1,
    transition: {
      duration: 0.5,
    },
  },
  exit: {
    transform: "scale(0) rotate(-720deg)",
    opacity: 0,
    transition: {
      duration: 0.3,
    },
  },
};


나쁜 서스펜션




const badSuspension = {
  hidden: {
    y: "-100vh",
    opacity: 0,
    transform: "scale(0) rotateX(-360deg)",
  },
  visible: {
    y: "-25vh",
    opacity: 1,
    transition: {
      duration: 0.2,
      type: "spring",
      damping: 15,
      stiffness: 500,
    },
  },
  exit: {
    y: "-100vh",
    opacity: 0,
  },
};

좋은 웹페이지 즐겨찾기