基于 flex 的 order 实现 carousel 轮播图

基于 flex 的 order 实现 carousel 轮播图

技术杂谈小彩虹2021-08-25 18:19:41230A+A-

原因

项目里需要使用轮播图,electron + vue 技术栈,项目应用一旦启动会持续运行24小时,并且机器性能较差,所以很关注两个点

  1. 内存泄漏
  2. 性能

目前社区的轮播组件,大多只是适用于常规 web 应用,经过内部测试后,并不能满足内存和性能方面的要求,所以需要自己实现轮播组件

思路

最开始找到了这篇文章,里面讲解了传统的轮播图实现思路和作者原创的轮播思路,并在文末给出了性能较高的原创方案。

作者的原创方案性能是很高了,但是我注意到每次执行轮播都需要移动一个 DOM 节点,这会触发浏览器重排重绘,性能依旧不够高,还可以继续优化。

首先想到了 flex 布局的 order 属性:https://developer.mozilla.org/zh-CN/docs/Web/CSS/order

兼容性

可以看到只有现代浏览器才支持,如果要兼容老久浏览器就不用考虑本方案了,我的环境是electron 2.0,集成的chrome 61,可使用。

实现方案

本文章只记录实现方案与伪代码,不会给出 demo。

基本功能实现

html结构

<div class="carousel">
  <div class="carousel-container" style="transition-duration: 0ms; transform: translate3d(0px, 0px, 0px);">
    <!-- 轮播列表元素 -->
    <div class="carousel-item" style="order: 0;"></div>
    <div class="carousel-item" style="order: 1;"></div>
    <div class="carousel-item" style="order: 2;"></div>
    <div class="carousel-item" style="order: 3;"></div>
    <div class="carousel-item" style="order: 4;"></div>
  </div>
</div>
<style> .carousel { width: 100%; } .carousel-container { width: 100%; display: flex; transition-property: transform; } .carousel-item { width: 100%; } </style>

从里面元素开始解释

  1. 父级设置 display: flex ,子级可以通过 order 属性实现排序,这种排序虽然依然会引发重排和重绘,但是开销更小
  2. 外围一层元素,使用 transition 实现 动画,使用 transform 的 translate3d 实现硬件加速与显示范围。在非动画状态,X轴的位置永远都是 0,在动画状态,才给 X轴 赋值,所以整个组件其实就是在做两件事: 顺序X轴位置(也就是动画)
  3. 顺序:非动画状态需要 X 轴一直为0,那么就要保证当前要显示的轮播元素的 order 值最小,我暂时约定最小为 0,因为动画涉及到下一张,所以当前轮播的order 为 0,下一张为 1,其他的只要大于1 即可。
  4. 动画,如果需求是切换的时候不需要动画,那么保证顺序就已经完成了轮播切换了,但需求通常需要动画。动画的实现由三部分,起始状态结束状态重置状态
  5. 起始状态:动画一开始,就是要在当前轮播元素开始,对应的X轴是0,起就是静止状态,所以起止状态不需要设置,默认就是了,所以通常其实状态无需处理
  6. 结束状态:结束的状态是下一张轮播元素完全显示,也就是X增加一个 轮播元素的宽度。动画时间 transition-duration 赋值 500ms,就能实现动画。
  7. 重置状态:动画完成后,重新计算各个元素的 order 值,把 X 轴重设为0,动画时间重设为0

到此就完成了轮播组件的基本功能

功能扩展

自动轮播

先实现一个函数 next() 方法,定时调用

拖动滚动

  1. 记录开始拖动时鼠标位置的 X轴
  2. 移动过程中获取鼠标位置X轴,减去开始拖动时的X轴位置,得到X轴移动的距离,再把这个距离数字赋值给 translate3d 的X轴

反向动画与拖动

通常的轮播都是 从右往左 滚动的,但是有时需要兼容 从左往右,实现方案:

非动画状态无需调整,主要关注动画状态。

  1. 排序:要反过来排序,当前显示的元素 order 为0,下一张为 -1,其他的小于 -1即可
  2. 动画的不同状态都需要调整
  3. 起始状态:X轴位置:-1 * (轮播条数 - 1) * 轮播宽度
  4. 结束状态:X轴位置:-1 * (轮播条数 - 与上条间隔数量) * 轮播宽度
  5. 重置状态:X轴位置:0,排序重置为正向

反向拖动,如果拖动的时候拖动的距离是个正数,则马上更新顺序为反向,如果为负数,马上更新顺序为正向

总结

该方案的性能很高,但是兼容性不太好。而且实现过程中,对元素的排序计算如果涉及到反向动画的话会比较复杂

点击这里复制本文地址 以上内容由权冠洲的博客整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

支持Ctrl+Enter提交

联系我们| 本站介绍| 留言建议 | 交换友链 | 域名展示
本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除

权冠洲的博客 © All Rights Reserved.  Copyright quanguanzhou.top All Rights Reserved
苏公网安备 32030302000848号   苏ICP备20033101号-1
本网站由 提供CDN/云存储服务

联系我们