基于 flex 的 order 实现 carousel 轮播图

缘由

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

  1. 内存泄漏
  2. 性能

目前社区的轮播组件,大多只是适用于常规 web 应用,通过内部测试后,并不能知足内存和性能方面的要求,因此须要本身实现轮播组件html

思路

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

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

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

兼容性

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

实现方案

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

基本功能实现

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

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

功能扩展

自动轮播

先实现一个函数 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,排序重置为正向

反向拖动,若是拖动的时候拖动的距离是个正数,则立刻更新顺序为反向,若是为负数,立刻更新顺序为正向

总结

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

相关文章
相关标签/搜索