7a7191ead5f47497a2ae5b2ebccf83ef.png

目标:为react组件轻松的添加动画效果。

<Transition
  in={ flag } // 控制动画展示的变量
  timeout={ 300 } // 动画持续时间
  animation='zoom-in-top‘
>
  { node }
</Transition>

拿导航栏的鼠标移入效果举例:

6d5d84ff10a5f6cf6ca0d6ec177771dd.png

鼠标移入时,下拉框展示,箭头向上旋转180;鼠标移出时,箭头向下旋转180,然后弹出层消失。

解决方案: 记录一个状态,当鼠标点击时,给这个元素添加一个类名,再次点击时,取消这个类名。

现在添加css效果,一开始的时候,ul是不展示的,即不显示在页面中。让元素不显示在页面中有两种方法:

  1. 元素存在于页面,但是看不见,使用opacity属性,设置为0
  2. 使用display:none,让元素不存在于页面。

这里初始的时候,显然只能使用第二种,因为第一种容易发生误点的情况。

但是这种情况存在一个问题,就是当组件再次点击消失的时候,display属性设置为none之后,其动画效果失效了,所以会导致在再次点击关闭的时候没有动画效果。

所以此时,我们引入第三方的动画插件库,来帮助我们解决这个问题.

  1. 快速上手使用CSSTransition
yarn add react-transition-group
yarn add @types/react-transition-group
import { CSSTransitionGroup } from 'react-transition-group'

<CSSTransition 
  in={inProp} 
  timeout={200} 
  classNames="my-node”
>
  <div>
    hello world
  </div>
</CSSTransition>

然后在样式组件上写入:

.my-node-enter {
  opacity: 0;
}
.my-node-enter-active {
  opacity: 1;
  transition: opacity 200ms;
}
.my-node-exit {
  opacity: 1;
}
.my-node-exit-active {
  opacity: 0;
  transition: opacity 200ms;
}

这样就给hello world元素添加上了一个简单动画。

2. 使用CSSTransition解决刚才的问题

因为该组件库有一个属性,unmountOnExit,即当in属性变化时,如果变为true,则会在当前页面渲染出内部元素,当为false时,会自动删除其中的节点。

所以我们将该属性附上,并添加一个appear属性,当初始化时动画也生效

<CSSTransition 
  in={inProp} 
  timeout={200} 
  classNames="my-node”
  unmountOnExit
  appear
>
  <div>
    hello world
  </div>
</CSSTransition>

3. 接下来,我们对于该组件做一次类似Icon组件的二次封装,将通用的属性设置为默认属性,并提供一些常用的动画效果

import React from 'react'
import { CSSTransition } from 'react-transition-group'
import { CSSTransitionProps } from 'react-transition-group/CSSTransition'

type TAnimationName = 'zoom-in-top' | 'zoom-in-left'

type TransitionProps = CSSTransitionProps & {
    animation?: TAnimationName,
    wrapper? : boolean,
  }

const Transition: React.FC<TransitionProps> =  (props) => {
    const { children, classNames, animation, wrapper, ...restProps } = props
    console.log('classNames', classNames);
    console.log('animation', animation);
    
    return (
        <CSSTransition
            classNames={classNames ? classNames : animation}
            {...restProps}
        >
            { children }
        </CSSTransition>
    )
}

Transition.defaultProps = {
    unmountOnExit: true,
    appear: true,
  }

export default Transition

这样我们就能够使用方便的动画效果:

<Transition
  in={ flag } // 控制动画展示的变量
  timeout={ 300 } // 动画持续时间
  animation='zoom-in-top‘
>
  { node }
</Transition>
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐