likes
comments
collection
share

react组件 轮播图组件实现思路

作者站长头像
站长
· 阅读数 18

前言

继续react组件库

轮播图实现你要考虑的几个点:

  • 使用javascript实现轮播滚动动画和css实现动画哪个更好?
  • 如果使用css动画实现,如何解决css动画期间,继续点击轮播图下一张不会影响到正在执行的滚动动画?
  • 如何实现点击去第n张图的动画?

示例(arco组件官网):arco.design/react/compo…

js和css动画性能对比

你知道为什么css动画要比js实现动画性能更好吗?

这就要谈到浏览器渲染流水线中,每一帧渲染要经历哪些过程了,简单的来说,就是先执行js有关的内容,然后渲染线程绘制位图。

所以js执行动画的时候要从流水线从头开始计算,然后重绘和回流走一遍,而css如果单独把这个动画提到一个图层,那么重绘和回流(轮播不涉及位置重新计算,所以也就没有了回流),只需要一个重绘就行了,所以对于浏览器渲染来说,压力小很多。

但是js执行也有提升性能的办法,就是在requestAnimationFrame环节执行动画,但是还是不如css动画的原因在于,css动画的合成是有gpu加速的(需要设置一些css属性),所以处理速度快的多,综合来说,技术选型上使用了css动画。

css动画实现原理

首先点击下一张图,会发生什么情况。

简单来说说,就是设置一些变量表示此时正在执行轮播动画,并且轮播的图片的index记录下来,在执行完动画,然后做一些状态更改。详细情况如下:

  • 如果没有正在执行动画,并且下一张跟这一张图不是同一张,则进入下一步,否则退出
  • 将 isAnimating 设置为 true,表示正在执行动画
  • 将 targetIndex设为当前图片在图片数组的index,表示要滚动到该幻灯片
  • 将 previousIndex 设置为上一张图的索引,表示上一个幻灯片的索引,也就是现在的图片就是下次轮播的上一张图
  • 触发onChange事件,表示此时已经开始轮播了
  • 创建一个 setTimeout 定时器,等待指定的 moveSpeed 时间(毫秒),时间到了就把 isAnimating 设置为 false,表示动画已经执行完毕。

关键原理在于,当按下一页的时候,给当前的图片加一个class,给即将出现的图片加一个class,从而实现css动画,啥意思,举例:

                [item-slide-out]:
                  isAnimating && index === previousIndex,

上面是arco的轮播图源码,我解释下。

item-slide-out,也就是当前图片退出,退出触发的前提是当前图片的index等于previousIndex,previousIndex是不是上面我们已经说了,在每次执行动画的时候,是不是把准备走的这张图,设置到了previousIndex中,所以每当我们点击下一张的时候

我们就会把当前图片上的dom增加一个item-slide-out的class,这个calss本质上是增加了一个animation的css动画

@keyframes ~'@{prefix}-carousel-slide-x-out' {
  from {
    transform: translateX(0);
  }

  to {
    transform: translateX(-100%);
  }
}

也就是利用translateX来使一张图从左边出去

  [item-slide-in]:
                  isAnimating && isCurrent,

上面这个css的class是不是也很好理解了,就是下一张图从右边进来

  from {
    transform: translateX(100%);
  }

  to {
    transform: translateX(0);
  }
}

如何解决css动画期间,继续点击轮播图下一张不会影响到正在执行的滚动动画

上面我们已经说了,有个isAnimating参数,表示是否正在执行动画,如果正在执行,继续点击下一张是没有效果的。

如何让css动画时间跟js时间同步

比如外部传入动画时间执行500ms,那么我们上面也分析了,设置了一个定时器,css动画500ms它自己执行,因为有animation这个css属性可以设置,js就通过定时器执行500ms,然后执行完毕设置isAnimating参数为false,表示执行完动画

从而达到动画同步的效果,但是我们知道定时器有可能有问题,但因为动画执行时间很短,基本没不会有bug。

如何实现点击去第n张图的动画

这个问题也是通过我们之前介绍的方法,之前我们说了是点击下一张的时候,设置targetIndex为下一张的index,那去第n张,是不是设置为去第n张的index就可以了

最后,轮播图基本实现是不是超级简单啊,留个思考题,如何实现如下的轮播(从css样式上考虑)

react组件 轮播图组件实现思路

转载自:https://juejin.cn/post/7208009506541715514
评论
请登录