原生JS实现移动端web轮播图详解(结合Tween算法造

相信大家应该都知道,移动端的轮播图是我们比较常见的需求, 我们最快的实现方式往往是 使用第三方的代码, 例如 swiper , 但当遇到一些比较复杂的轮播图需求时, 往往是束手无策,不知道怎么改.      

所以我们要尝试去自己造一些轮子, 以适应各种复杂多变的需求;  另外一点, 自己写的代码如果有bug是很容易修复的, 对自身的提高也很大.

在没有阅读swiper源码的过程下,我尝试自己实现一个简易而不失实用的移动端轮播图, 经过几个小时的思考和实践终于还是实现了(如图):

原生JS实现移动端web轮播图详解(结合Tween算法造


实现移动端的轮播图要比pc复杂一些,主要表现在以下几个方面:

1.轮播图要适应不同宽度/dpr的屏幕 

2.需要使用 touch相关的事件 

3.不同机型对 touch事件支持的不太一样,可能会有一些兼容性问题 

4.手指移动图片一部分距离,剩下的距离需要自动完成 

5.自动完成距离需要有 ease 时间曲线 

但编程解决问题的思路都是差不多的,

我们在使用轮播图的时候可以仔细观察,通过现象看到本质:

我们在使用轮播图的时候可以仔细观察,通过现象看到本质: 

手指放在图片上, 手指向左或者向右移动, 图片也随之移动; 

手指移动的距离少时,图片自动复原位置;手指移动的距离多时,自动切换到下一张; 

手指向左或者向右移动的快时,会切换到下一张; 

图片轮播是无限循环的, 我们需要采用  3 1 2 3 1的方式来实现, 即 N+2张图来实现N张图的无限循环轮播 

我们通过分析现象,可以提出一个基本实现方案:

1. 手指触摸事件可以通过 touchstart touchmove touchend 3个事件来实现 

2.在手指 touchstart的时候我们需要记录 手指的x坐标,  可以使用 touch的pageX属性; 还有 这个时间点, 

3.手指touchmove的时候我们也需要记录pageX,并且记录累计移动的距离 moveX 

4.手指离开的时候,记录时间点, 根据前两步计算的 x方向移动的距离,时间点之差 

5.通过比较x方向移动距离来判断移动方向, 以及是否应该切换到下一张图; 根据时间判断用户是否进行了左右扫动的操作 

6.移动图片可以使用 translate3d来实现,开启硬件加速 

7.移动一段距离需要 easeOut效果,我们可以使用 Tween算法中的easeOut来实现我们每次移动的距离; 当然也可以使用 js设置 transition动画 

实现源码(仅供参考):

head头部样式

<head> <meta charset="UTF-8"> <meta content="width=device-width,initial-scale=.5,maximum-scale=.5"> <title>移动端轮播图</title> <style> * { box-sizing: border-box; margin: 0; padding: 0 } .banner { overflow: hidden; width: 100%; height: 300px } .banner .img-wrap { position: relative; height: 100% } .banner img { display: block; position: absolute; top: 0; width: 100%; height: 100% } </style> </head>

HTML结构

<div> <div> <img src="https://www.jb51.net/images/banner_3.jpg" data-index="-1"> <img src="https://www.jb51.net/images/banner_1.jpg" data-index="0"> <img src="https://www.jb51.net/images/banner_2.jpg" data-index="1"> <img src="https://www.jb51.net/images/banner_3.jpg" data-index="2"> <img src="https://www.jb51.net/images/banner_1.jpg" data-index="3"> </div> </div>

JS代码1, easeOut动画式移动,

这里的   HTMLElement.prototype.tweenTranslateXAnimate ,是给所有的HTML元素类扩展的tweenTranslateXAnimate方法

移动一段距离我们需要使用定时器来帮助我们完成,这个重复的操作

<script> HTMLElement.prototype.tweenTranslateXAnimate = function (start, end, callback) { var duration = 50; var t = 0; var vv = end - start; var Tween = { Quad: { easeOut: function (t, b, c, d) { return -c * (t /= d) * (t - 2) + b; } } }; this.timer = setInterval(function () { var dis = start + Tween.Quad.easeOut(++t, 0, vv, duration); this.style.transform = 'translate3d(' + dis + 'px, 0, 0)'; if (vv > 0 && parseInt(this.style.transform.slice(12)) >= end) { this.style.transform = 'translate3d(' + parseInt(dis) + 'px, 0, 0)'; clearInterval(this.timer); callback && callback(); } if (vv < 0 && parseInt(this.style.transform.slice(12)) <= end) { this.style.transform = 'translate3d(' + parseInt(dis) + 'px, 0, 0)'; clearInterval(this.timer); callback && callback(); } }.bind(this), 4); } </script>

touch事件部分

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wygzsp.html