• React之组件间过渡动画如何实现


    一、是什么

    在日常开发中,页面切换时的转场动画是比较基础的一个场景

    当一个组件在显示与消失过程中存在过渡动画,可以很好的增加用户的体验

    react中实现过渡动画效果会有很多种选择,如react-transition-groupreact-motionAnimated,以及原生的CSS都能完成切换动画

    二、如何实现

    react中,react-transition-group是一种很好的解决方案,其为元素添加enterenter-activeexitexit-active这一系列勾子

    可以帮助我们方便的实现组件的入场和离场动画

    其主要提供了三个主要的组件:

    • CSSTransition:在前端开发中,结合 CSS 来完成过渡动画效果
    • SwitchTransition:两个组件显示和隐藏切换时,使用该组件
    • TransitionGroup:将多个动画组件包裹在其中,一般用于列表中元素的动画

     CSSTransition

    其实现动画的原理在于,当CSSTransitionin属性置为true时,CSSTransition首先会给其子组件加上xxx-enterxxx-enter-activeclass执行动画

    当动画执行结束后,会移除两个class,并且添加-enter-doneclass

    所以可以利用这一点,通过csstransition属性,让元素在两个状态之间平滑过渡,从而得到相应的动画效果

    in属性置为false时,CSSTransition会给子组件加上xxx-exitxxx-exit-activeclass,然后开始执行动画,当动画结束后,移除两个class,然后添加-enter-doneclass

    如下例子:

    1. export default class App2 extends React.PureComponent {
    2. state = {show: true};
    3. onToggle = () => this.setState({show: !this.state.show});
    4. render() {
    5. const {show} = this.state;
    6. return (
    7. <div className={'container'}>
    8. <div className={'square-wrapper'}>
    9. <CSSTransition
    10. in={show}
    11. timeout={500}
    12. classNames={'fade'}
    13. unmountOnExit={true}
    14. >
    15. <div className={'square'} />
    16. </CSSTransition>
    17. </div>
    18. <Button onClick={this.onToggle}>toggle</Button>
    19. </div>
    20. );
    21. }
    22. }

    对应css样式如下:

    1. .fade-enter {
    2. opacity: 0;
    3. transform: translateX(100%);
    4. }
    5. .fade-enter-active {
    6. opacity: 1;
    7. transform: translateX(0);
    8. transition: all 500ms;
    9. }
    10. .fade-exit {
    11. opacity: 1;
    12. transform: translateX(0);
    13. }
    14. .fade-exit-active {
    15. opacity: 0;
    16. transform: translateX(-100%);
    17. transition: all 500ms;
    18. }

    SwitchTransition

    SwitchTransition可以完成两个组件之间切换的炫酷动画

    比如有一个按钮需要在onoff之间切换,我们希望看到on先从左侧退出,off再从右侧进入

    SwitchTransition中主要有一个属性mode,对应两个值:

    • in-out:表示新组件先进入,旧组件再移除;
    • out-in:表示就组件先移除,新组建再进入

    SwitchTransition组件里面要有CSSTransition,不能直接包裹你想要切换的组件

    里面的CSSTransition组件不再像以前那样接受in属性来判断元素是何种状态,取而代之的是key属性

    下面给出一个按钮入场和出场的示例,如下:

    1. import { SwitchTransition, CSSTransition } from "react-transition-group";
    2. export default class SwitchAnimation extends PureComponent {
    3. constructor(props) {
    4. super(props);
    5. this.state = {
    6. isOn: true
    7. }
    8. }
    9. render() {
    10. const {isOn} = this.state;
    11. return (
    12. <SwitchTransition mode="out-in">
    13. <CSSTransition classNames="btn"
    14. timeout={500}
    15. key={isOn ? "on" : "off"}>
    16. {
    17. <button onClick={this.btnClick.bind(this)}>
    18. {isOn ? "on": "off"}
    19. </button>
    20. }
    21. </CSSTransition>
    22. </SwitchTransition>
    23. )
    24. }
    25. btnClick() {
    26. this.setState({isOn: !this.state.isOn})
    27. }
    28. }

    css文件对应如下:

    1. .btn-enter {
    2. transform: translate(100%, 0);
    3. opacity: 0;
    4. }
    5. .btn-enter-active {
    6. transform: translate(0, 0);
    7. opacity: 1;
    8. transition: all 500ms;
    9. }
    10. .btn-exit {
    11. transform: translate(0, 0);
    12. opacity: 1;
    13. }
    14. .btn-exit-active {
    15. transform: translate(-100%, 0);
    16. opacity: 0;
    17. transition: all 500ms;
    18. }

    TransitionGroup

    当有一组动画的时候,就可将这些CSSTransition放入到一个TransitionGroup中来完成动画

    同样CSSTransition里面没有in属性,用到了key属性

    TransitionGroup在感知children发生变化的时候,先保存移除的节点,当动画结束后才真正移除

    其处理方式如下:

    • 插入的节点,先渲染dom,然后再做动画

    • 删除的节点,先做动画,然后再删除dom

    如下:

    1. import React, { PureComponent } from 'react'
    2. import { CSSTransition, TransitionGroup } from 'react-transition-group';
    3. export default class GroupAnimation extends PureComponent {
    4. constructor(props) {
    5. super(props);
    6. this.state = {
    7. friends: []
    8. }
    9. }
    10. render() {
    11. return (
    12. <div>
    13. <TransitionGroup>
    14. {
    15. this.state.friends.map((item, index) => {
    16. return (
    17. <CSSTransition classNames="friend" timeout={300} key={index}>
    18. <div>{item}</div>
    19. </CSSTransition>
    20. )
    21. })
    22. }
    23. </TransitionGroup>
    24. <button onClick={e => this.addFriend()}>+friend</button>
    25. </div>
    26. )
    27. }
    28. addFriend() {
    29. this.setState({
    30. friends: [...this.state.friends, "coderwhy"]
    31. })
    32. }
    33. }

    对应css如下:

    1. .friend-enter {
    2. transform: translate(100%, 0);
    3. opacity: 0;
    4. }
    5. .friend-enter-active {
    6. transform: translate(0, 0);
    7. opacity: 1;
    8. transition: all 500ms;
    9. }
    10. .friend-exit {
    11. transform: translate(0, 0);
    12. opacity: 1;
    13. }
    14. .friend-exit-active {
    15. transform: translate(-100%, 0);
    16. opacity: 0;
    17. transition: all 500ms;
    18. }
  • 相关阅读:
    pandas print输出格式设置
    玩转webpack(01):初识webpack
    智慧展览馆:基于AI智能识别技术的视频智慧监管解决方案
    实现element 下拉选择分页加载
    好莱坞编剧大罢工终于结束;与OpenAI创始人共进早餐;使用DALL-E 3制作绘本分享;生成式AI的基础设施架构 | ShowMeAI日报
    频率合成器的高性能架构实现技术
    L1-019 谁先倒 C++解法
    电脑提示msvcp140.dll丢失的解决方法(附带详细msvcp140.dll文件分析)
    【LeetCode】24. 两两交换链表中的节点
    leetcode.864 获取所有钥匙的最短路径 - bfs+状态压缩+最短路+位运算
  • 原文地址:https://blog.csdn.net/Ming_xm/article/details/133944885