欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

在React项目中集成动画库

程序员文章站 2022-05-03 09:48:17
...

(一)前言
其实,对于常用动画,大部分基于css的transition 和animation实现,在总结目前react动画使用时候,大概发现类似本文 React组件动画方案,我们以目前css-module的方式在加载scss文件,并配置了css支持,css不会提供module功能

(二)集成animate.css
本身,我们最方便是直接集成animate.css,所以大部分场景,我们做入场动画,其实可以使用animate.css 内置的动画效果,代码如下

// 增加一个从底部向上的动画
<div
  className={helpers.reactClassNameJoin(
  styles.footerButtonView,
  'animated slideInUp',
  )}
>
{....}
</div>

2.1 触发,如果直接设置在元素的class上面,需要触发动画。

方案一是,直接移除dom。

方案二是,在这个className(animated slideInUp)时候,增加一个state判断如下 isVisible ? ‘animated slideInUp’ : ‘’

2.2 自定义动画,如果内置的动画方法不能满足业务需求的情况下,我们就需要自定义动画效果,这时候需要怎么做呢?
CSS_Animations 官方文档

首先我们来自定以一个从底部淡入的动画

声明 keyframes

@keyframes homeFadeInLeft {
  0% {
    opacity: 0;
    transform: translate3d(-60px, 0, 0);
  }
  100% {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

@keyframes homeFadeInRight {
  0% {
    opacity: 0;
    transform: translate3d(60px, 0, 0);
  }
  100% {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

@keyframes homeFadeInBottom {
  0% {
    opacity: 0;
    transform: translate3d(0, 40px, 0);
  }
  100% {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

定义animation名称

// 入场动画
.animateFadeIn {
  .phoneLeft {
    animation: homeFadeInLeft $animated-duration forwards;
    animation-delay: 0s;
  }

  .phoneCenter {
    animation: homeFadeInBottom $animated-duration forwards;
    animation-delay: 0.1s;
  }

  .phoneRight {
    animation: homeFadeInRight $animated-duration forwards;
    animation-delay: 0.2s;
  }
}

这里我只在最外层容器增加了animateFadeIn名称的classname 并且使用animation给不同的div声明不同的动画,并且使用animation-delay设置一个延迟效果

使用动画

<div
  className={helpers.reactClassNameJoin(
  'animated',
  styles.animateFadeIn,
)}
>
  <div className={styles.phoneLeft}>phoneLeft</div>
  <div className={styles.phoneCenter}>phoneCenter</div>
  <div className={styles.phoneRight}>phoneRight</div>
</div>

到这步,我们就可以看到,能使用内置动画了。

(三)实现进场和出场动画(这里以web例子)
antd推荐社区组件

这里我们以rc-animate来实现进入场动画,基于我们当前的项目,讲解如何在项目中内置动画,这里依然分为三步

声明 keyframes

/* rc-animate库的动画
*/

@keyframes homeFadeInLeft {
  0% {
    opacity: 0;
    transform: translate3d(-60px, 0, 0);
  }
 100% {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

@keyframes homeFadeOutLeft {
  0% {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
  100% {
    opacity: 0;
    transform: translate3d(-60px, 0, 0);
  }
}

这里和项目动画库不一样,定义的keyframes需要以css后缀直接导入,在当前页面直接import,引入scss文件不生效

定义animation名称

@mixin enterCommon($delay: 0.2s) {
  opacity: 0;
  animation-duration: 0.8s;
  animation-delay: $delay;
  animation-fill-mode: both;
  animation-timing-function: ease;
  animation-play-state: paused;
}

@mixin leaveCommon() {
  animation-duration: 0.5s;
  animation-fill-mode: both;
  animation-timing-function: ease;
  animation-play-state: paused;
}

// 切换动画
:global {
  .fadeLeft-enter {
    @include enterCommon();

  &.fadeLeft-enter-active {
    animation-name: bobHomeFadeInLeft;
    animation-play-state: running;
  }
}

.fadeLeft-leave {
  @include leaveCommon();

  &.fadeLeft-leave-active {
    animation-name: bobHomeFadeOutLeft;
    animation-play-state: running;
  }
 }
}

因为插件绑定了四个class,分为事*-enter, *-enter-active, *-leave, -leave-active。但是声明时候是以transitionName=’’ 这种当时声明,所以需要使用global在scss中进行暴露,不能使用css module方式。

使用动画

import Animate from 'rc-animate';

<Animate component='' transitionName='fadeLeft'>
  {isVisible ? (
    <div className={styles.phoneLeft}>
    <ImgLoader
      className={styles.phoneImg}
      thumb={'/assets/home/20190922/thumb/client/img_sport2.png'}
      image={'/assets/home/20190922/client/img_sport2.png'}
    />
  </div>
) : null}
</Animate>

这里需要注意是,因为Animate需要做入场离场,然后不能把这个元素标签移除,把需要动画的元素用Animate标签包装,内部需要用一个标志位,控制他直接是否移除dom,然后实现进场于离场

(四)结语

对于目前大部分场景的react web应用而言,多数实现都是进场动画,相对苛刻情况下,会使用进入场,但是,一般的简单动画,也会自己写,当然,如何要使用高性能的动画方案,那么还是需要使用
替换gif
gsap