react简单写一个transition动画组件然后在modal组件中应用

1. 动画组件

原理: 利用transition和class类的切换执行transition的动画效果

import React from "react";
import _ from "lodash";

interface IProps {
  name: string;
  children: React.ReactNode;
  transitionShow: boolean;
}
const MyTransition = (props: IProps) => {
  const { name, children, transitionShow } = props;

  const getTransition = (name, transitionShow = true) => {
    const val = transitionShow ? "-leave-active" : "-leave-to";
    return name + val;
  };

  return <div className={getTransition(name, transitionShow)}>{children}</div>;
};

export default MyTransition;

scss部分:

  // transition动画部分
  .myOpacity-enter,
  .myOpacity-leave-to {
    opacity: 0;
    // 因为picker滚动区域有过transform, 这里也写transform的话会导致本不该滚动的地方滚动了
    margin: 30px;
    // animation: fadeIn 0.5s steps(1);
    transition: all 0.5s ease;
  }

  .myOpacity-enter-active,
  .myOpacity-leave-active {
    transition: all 0.5s ease;
  }

  @keyframes fadeIn {
    20% {
      opacity: 0.9;
      margin: 30px;
    }

    40% {
      opacity: 0.8;
      margin: 25px;
    }

    60% {
      opacity: 0.7;
      margin: 20px;
    }

    80% {
      opacity: 0.6;
      margin: 15px;
    }

    100% {
      opacity: 0.5;
      margin: 10px;
    }
  }



  .myPopup-enter,
  .myPopup-leave-to {
    transform: translateY(100vh);
    // animation: popupTranslateY 0.5s steps(1);
    transition: all 0.5s ease;
  }

  .myPopup-enter-active,
  .myPopup-leave-active {
    transition: all 0.5s ease;
  }

  @keyframes popupTranslateY {
    20% {
      transform: translateY(10vh);
    }

    40% {
      transform: translateY(20vh);
    }

    60% {
      transform: translateY(40vh);
    }

    80% {
      transform: translateY(60vh);
    }

    100% {
      transform: translateY(100vh);
    }
  }

使用方法, 比如一个modal组件需要动画的话:

import React, { useEffect, useState, ReactNode, useImperativeHandle, forwardRef } from "react";
import _ from "lodash";
import "./Picker.scss";
import * as ReactDOM from "react-dom";
import MyTransition from "./MyTransition";

interface IProps {
  isShow: boolean;
  setIsShow: (arg1: boolean) => void;
  children: ReactNode;
}

const MyPickerModal = forwardRef((props: IProps, ref) => {
  const { isShow, setIsShow, children } = props; // 解构props, 得到需要使用来自父页面传入的数据

  const [pickerIsShow, setPickerIsShow] = useState(props.isShow);
  useEffect(() => {
    setPickerIsShow(isShow);
  }, [isShow]);

  useImperativeHandle(ref, () => ({
    close,
  }))

  function close() {
    setTimeout(() => {
      setPickerIsShow(false);
      // 延迟关闭, 因为MyTransition需要这段时间差执行动画效果, 否则看起来像没有动画效果似的突然消失了
      setTimeout(() => {
        setIsShow(false);
      }, 500);
    }, 0);
  } // 点击取消按钮

  return ReactDOM.createPortal(
    <div className="picker-container">
      <MyTransition name="myPopup" transitionShow={pickerIsShow}>
        {isShow && <section className="pop-cover" onClick={close}></section>}
      </MyTransition>
      <MyTransition name="myOpacity" transitionShow={pickerIsShow}>
        {isShow && children}
      </MyTransition>
    </div>,
    document.body
  );
});

export default MyPickerModal;

ReactDOM.createPortal(element, 要插入这个elment的父元素, 一般写body, 也自己去html文件加一个元素, 插入到那个元素中去

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值