En

Анимированное модальное окно в React с использованием – onAnimationEnd

13.08.2023

Анимированное модальное окно в React с использованием - onAnimationEnd

В данном компоненте, при создании анимации, применяется – onAnimationEnd, как и в этом случае. onAnimationEnd – это обработчик события animationEnd, которое вызывается, когда завершается CSS-анимация элемента. В этом компоненте не используются сторонние библиотеки для анимации и когда модальное окно закрыто, оно отсутствует в DOM.

 

App.jsx

import { useState } from "react";
import Modal from "./components/modal";

function App() {
  const [showModal, setShowModal] = useState(false);
  return (
    <div className="App">
      <button
        onClick={() => {
          setShowModal(true);
        }}
      >
        Open modal
      </button>  
      <Modal buttonShowModal={showModal} setButtonShowModal={setShowModal} />
    </div>
  );   
}
export default App;

 

index.jsx (modal)

import styles from "./modal.module.css";
import { useState, useEffect, useRef } from "react";
import Close from "../svg/Icon/Close";
import Horse from "../svg/Drawing/Horse";

export default function Modal({ buttonShowModal, setButtonShowModal }) {
  const [showModal, setShowModal] = useState(false);
  useEffect(() => {
    if (buttonShowModal) {
      setShowModal(true);
    }
  }, [buttonShowModal]);
  const [fadeOut, setFadeOut] = useState(false);

  // Отслеживание кликов за пределами модального окна
  const modalRef = useRef();
  useEffect(() => {
    if (modalRef.current) {
      const handler = (e) => {
        if (!modalRef.current.contains(e.target)) {
          setFadeOut(true);
        }
      };
      document.addEventListener("mousedown", handler);
      return () => {
        document.removeEventListener("mousedown", handler);
      };
    }
  });

  return (
    <>
      {showModal && (
        <div
          className={
            fadeOut
              ? `${styles.modal_wrap} ${styles.modal_wrap__fade_out}`
              : `${styles.modal_wrap}`
          }
          onAnimationEnd={(e) => {
            if (e.animationName === styles.fadeOut) {
              setFadeOut(false);
            }
          }}
        >
          <div
            ref={modalRef}
            className={
              fadeOut
                ? `${styles.modal} ${styles.modal__fade_out}`
                : `${styles.modal}`
            }
            onAnimationEnd={(e) => {
              if (e.animationName === styles.fadeOut) {
                setShowModal(false);
                setFadeOut(false);
                setButtonShowModal(false);
              }
            }}
          >
            <Horse />
            <div
              onClick={() => {
                setFadeOut(true);
                setButtonShowModal(false);
              }}
              className={styles.close_button}
            >
              <Close />
            </div>
          </div>
        </div>
      )}
    </>
  );
}

 

modal.module.css

.modal_wrap {
  display: flex;
  justify-content: center;
  align-items: center;
  background: rgba(0, 0, 0, 0.069);
  position: fixed;
  width: 100%;
  height: 100%;
  animation: fadeInModalWrap 0.5s forwards;
  opacity: 0;
  left: 0;
  top: 0;
}

.modal_wrap__fade_out {
  animation: fadeOut 0.5s forwards;
  opacity: 1;
}

@keyframes fadeInModalWrap {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes fadeOut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

.modal {
  width: 100%;
  max-width: 260px;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 250px;
  border-radius: 5px;
  position: relative;
  animation: fadeInModal 0.8s forwards;
  background-color: rgb(255, 255, 255);
  margin-right: 15px;
  margin-left: 15px;
}

.modal__fade_out {
  animation: fadeOut 0.5s forwards;
}

@keyframes fadeInModal {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.close_button {
  position: absolute;
  right: 5px;
  top: 5px;
  border: 2px solid rgb(90, 90, 90);
  cursor: pointer;
  border-radius: 3px;
}

GitHub Live

Поделиться

Копировать

BTC (Network BTC) - 1C2EWWeEXVhg93hJA9KovpkSd3Rn3BkcYm

Ethereum (Network ERC20) - 0x05037ecbd8bcd15631d780c95c3799861182e6b8

Этот сайт использует файлы cookies. Нажимая кнопку 'Принять' или продолжая пользоваться сайтом, вы соглашаетесь на использование файлов cookies.