原理
假设无缝滚动的容器是 ul 标签,滚动元素是 li 标签。先克隆第一个 li 标签和最后一个 li 标签,克隆的第一个 li 标签添加到列表末尾,克隆的最后一个 li 标签插入到列表头部。如果列表向左滑动,当滑动到克隆的第一个元素时,迅速将容器定位到真正的第一个元素,如果列表向右滑动,当滑动到最后一个元素时,迅速将容器定位到真正的最后一个元素,这样就可以在视觉上形成无缝的效果。
实现
在实现容器位置移动的时候,可以使用 position 定位加 left/top 实现,也可以使用 translate 2D 变换来实现,建议使用 translate 2D 变换来实现,因为使用 translate 2D 变换只会引起重绘,使用 position 定位加 left/top 会引起重排,translate 2D 变换的性能更好。这里不用 translate 3D,是因为 translate 3D 会有比较多的兼容性问题,同时强制 GPU 加速也不是在任何场景下都能提升性能。
移动端下的手势操作,touchstart 的时候记录开始的 x 轴坐标,touchmove 触发时获取当前 x 轴坐标与开始时坐标的差值,借助 translate 移动同样的距离,从而实现跟手的效果。
移动的动画使用 requestAnimationFrame 实现,一方面是因为 setTimeout 或 setInterval 的时间间隔并不精确,你设置时间间隔为 3 秒,实际执行时有可能是 10 秒,另一方面 requestAnimationFrame 可以告诉浏览器下次重绘之前执行回调函数更新动画,因此使用 requestAnimationFrame 实现动画会更加流畅。
具体实现可以参考 s-carousel
模块化
JS 代码有很多模块化的方案,分别为 AMD、CMD、UMD、commonJS 和 ES6 module 。
AMD(Asynchronous module definition),叫异步模块定义,采用异步的方式加载模块,模块的加载不影响它后面语句的运行,主要在浏览器环境采用此种模块化方案。
CMD(Common Module Definition),叫通用模块定义,它跟 AMD 类似,也是异步加载模块,与 AMD 的不同在于依赖的处理时机不同,AMD 是会提前加载依赖,即使没有使用到这个依赖,CMD 是在使用到这个依赖的时候才会加载这个依赖,CMD 也是适用于浏览器端的依赖。
UMD(Universal Module Definition),叫万能模块定义,是一种即能够在服务端使用也能在浏览器端使用的模块化方案。
CommonJS,是 NodeJS 一开始采用的模块化方案,是适用于服务端采用的模块化方案,采用同步的方式加载模块。
ES6 Module,是 ES6 中规定的模块化方案,未来 AMD、CMD、UMD、CommonJS 可能会被弃用,统一采用 ES6 Module。
s-carousel 采用的是 UMD 的模块化方案。
ES6 Module 与 CommonJS 的区别
-
CommonJS 模块输出的是一个值的拷贝(浅拷贝),ES6 Module 模块输出的是值的引用。当代码需要被执行的时候,JS 引擎会使用这个引用去被加载的模块里面去取值。
-
CommonJS 模块是
运行时加载,在加载时先加载整个模块,生成一个对象,再从这个对象中取值。 ES6 Module 是编译时加载,通过export命令显示指定到处的值,在import时指定加载某个值,而不是加载整个模块。