React动画:react-transition-group 使用以及动画原理
简单介绍
React Transition Group 是一个 React 库,用于管理和处理在 React 应用中的过渡动画效果。它提供了一组组件,可以帮助你在组件的进入和退出时应用动画效果。
这个动画库在npm上周下载量高达 1200 多万:npm
我自己对它的理解是一个轻量、简单的动画库,它甚至不算一个动画库,它只提供触发机制、具体动画需要自行编写,它可以应对大量常见简单动画,如果你需要编写高级动画,建议用react-spring
、framer-motion
等。
它主要包含四个组件Transition
,CSSTransition
,SwitchTransition
,TransitionGroup
这四个组件,本文主要以CSSTransition
进行讲解。
CSSTransition
CSSTransition
是我们最常用的一个组件,它提供两组动画的切换,一般我们可以用于元素的隐藏和显示,可以应对大部分的简单动画,相比于我们手动去添加类名等操作,它会更加方便。
基本使用:
我们需要用CSSTransition
组件来包裹需要做动画的元素,并且只能有一个children
元素。
正确写法✅✅✅
<CSSTransition in={show} timeout={2000} classNames="fade">
<div className=“box”></div>
</CSSTransition>
错误写法❌❌❌
<CSSTransition in={show} timeout={2000} classNames="fade">
<div className=“box”></div>
<div className=“box”></div>
</CSSTransition>
并且,CSSTransition
这个元素最终并不会渲染到页面中,只会留下box
元素。
再讲讲CSSTransition
组件常用的属性:
- in:用于动画的切换,boolean 值,分别对应进入和退出两组动画
- false -> true: 对应一组动画类名:*-enter、 *-enter-active、 *-enter-done
- true-> false:对应一组动画类名:*-exit、 *-exit-active、 *-exit-done
- timeout:动画的作用时间,单位:ms
- classNames:两种形式,字符串形式:指定动画类名的前缀。对象形式:指定每一个具体的类名
- unmountOnExit:元素在完成动画时是否从页面中移除该dom元素
- appear:指定元素首次渲染在页面时,是否进行动画。对应一组动画类名:*-appear、 *-appear-active、 *-appear-done
这边代码演示环境:
先来写一个最简单的示例,点击切换显示隐藏,使用 transform 和 opacity。
import React, { useState } from "react";
import styles from "./styles.module.scss";
import { CSSTransition, SwitchTransition } from "react-transition-group";
import { Button } from "antd";
const AnimationExample: React.FC = () => {
const [show, setShow] = useState(true);
return (
<div className={styles.app}>
<div className={styles.handle}>
<Button type="primary" onClick={() => setShow(!show)}>
切换
</Button>
</div>
<CSSTransition
in={show}
timeout={500}
classNames={{
enter: styles.fadeEnter,
enterActive: styles.fadeEnterActive,
enterDone: styles.fadeEnterDone,
exit: styles.fadeExit,
exitActive: styles.fadeExitActive,
exitDone: styles.fadeExitDone,
}}
>
<div className={styles.box}></div>
</CSSTransition>
</div>
);
};
export default AnimationExample;
.box {
width: 100px;
height: 100px;
background-color: orange;
border-radius: 24px;
}
.fade-enter {
opacity: 0;
transform: translateX(100%);
}
.fade-enter-active {
opacity: 1;
transform: translateX(0);
transition: all 0.5s;
}
.fade-enter-done {
opacity: 1;
transform: translateX(0);
transition: all 0.5s;
}
.fade-exit {
opacity: 1;
transform: translateX(0);
}
.fade-exit-active {
opacity: 0;
transform: translateX(100%);
transition: all 0.5s;
}
.fade-exit-done {
opacity: 0;
transform: translateX(100%);
transition: all 0.5s;
}
因为我这里使用了 css modules,并开启了类名自动转小驼峰,才是这种写法,也可以使用类名前缀写法(我这里指定了fade前缀),使用全局样式。
<CSSTransition in={show} timeout={500} classNames="fade">
<div className={styles.box}></div>
</CSSTransition>
效果如下:
简单分析过程:
初始时,我们设置in为true
,我们点击切换,in从 true
-> false
。
- 先后给 .box元素添加
.fade-exit
和.fade-exit-active
类名,元素根据类名开始做动画,并开始计时(timeout)。 - timeout时间到,移除
.fade-exit
和.fade-exit-active
这两个类名,并添加.fade-exit-done
类名,过程结束。
我们再次点击切换,in从 false
-> true
。
- 移除
.fade-exit-done
,并先后添加.fade-enter
和.fade-enter-active
,元素开始做动画,并开始计时(timeout)。 - timeout时间到,移除
.fade-enter
和.fade-enter-active
,并添加.fade-enter-done
。过程结束。
简单总结,CSSTransition 的动画原理就是在指定时刻添加添加类名和移除类名,通过 transition css属性达成平滑过渡,它并没有使用到 @keyframes
。
思考:timeout 到底是什么时间?
这个 api 挺疑惑的,是动画持续时间?NO!我们的动画时间已经在css中指定了:transition: all 0.5s;
。这个timeout准确来说应该是*-enter
和*-enter-active
(或者*-exit和 *-exit-active)的作用时间
我们从添加类名开始计时,timeout一到,就移除*-enter
和*-enter-active
,并添加*-enter-done
。
我们把动画放慢,可以清晰观察元素的状态
unmountOnExit
unmountOnexit属性用于当我们 in 从 true
-> false
动画结束后,是否从页面中移除该dom元素,默认为false,我们上面的例子可以看到是没有移除dom元素,我只是改变了透明度。
当我们设置为true
后,当 in 从 true
-> false
时,dom元素会从页面中移除,当 false
-> true
时,dom元素会被重新创建添加到指定位置。
<CSSTransition in={show} timeout={2000} classNames="fade" unmountOnExit={true}>
<div className={styles.box}></div>
</CSSTransition>
appear
我们尝试刷新一下浏览器,模拟一次页面初始化,每个dom第一次创建并挂载到页面上,发现这个dom元素并不会进行动画,如果我们想在 dom元素初次渲染就进行一次动画,可以使用appear
这个属性,并且在相关类名添加*-appear
、*-appear-active
、*-appear-enter
。
<CSSTransition in={show} timeout={2000} classNames="fade" appear={true}>
<div className={styles.box}></div>
</CSSTransition>
.fade-appear {
opacity: 0;
transform: translateX(100%);
}
.fade-appear-active {
opacity: 1;
transform: translateX(0);
transition: all 2s;
}
我们可以对比两个效果。
钩子函数
CSSTransition
还提供一组动画函数,用于在指定时刻进行调用,参数如下:
- el:进行过渡动画的 DOM 节点
- isAppearing:组件是否是首次出现(如果设置了
appear
属性)。
其中,onEnter、onEntering、onEntered提供两个参数:el、isAppearing
onExit、onExiting、onExited提供一个参数:el
<CSSTransition
in={show}
timeout={2000}
classNames="fade"
appear={true}
onEnter={(el, isAppearing) => console.log(el, isAppearing, "开始进入")}
onEntering={(el, isAppearing) => console.log("正在进入")}
onEntered={(el, isAppearing) => console.log("进入完成")}
onExit={(el) => console.log("开始退出")}
onExiting={(el) => console.log("正在退出")}
onExited={(el) => console.log("退出完成")}
>
文章到此就结束了,相信理解了 CSSTransition
的原理,SwitchTransition
,TransitionGroup
你也能轻松驾驭。
最后,创作不易,希望可以点个赞支持一下🥰🥰,若文章出现错误,还请指出。
转载自:https://juejin.cn/post/7251033389998456892