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文件加一个元素, 插入到那个元素中去