在React项目中集成动画库
(一)前言
其实,对于常用动画,大部分基于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