看到题目,我想大家中的很多人应该都是和我一样的疑惑,不用定时器去实现,那该咋整?毕竟用setInterval控制无缝轮播图中的图片切换太常见了,在网上随便搜一搜基本上都是如下这种写法。
timerID = setInterval(function () {
// 获得它当前位置 要求子元素和父级元素都要定位
var current = dom.offsetLeft;
// 移动距离减去当前距离,每次前进10px,直到到达,到达后停止定时器
if (Math.abs(target - current) > 10) {
current += target > current ? 10 : -10;
// 赋值给left
dom.style.left = current + "px";
} else {
dom.style.left = target + "px";
}
if (current == target) {
clearInterval(timerID);
}
}, 10);
至于其他类型的写法,当然有,但是很少见,比如 elementUi 中是控制各个子元素的 transform ,但是很遗憾,老版的有bug,我也没想出好的解决方案,至于新的 plus 版本的还没看过,不做评论。
为了后续讲解方便,先放完整代码
起因
因为项目中有个页面涉及到的 setInterval 这个API比较多,导致了一些意料之外的问题,我们老大就很生气,表示不要再让这个API出现在项目中,凡是涉及到的统统替换掉。然后我负责的是轮播图,我听了就很尴尬,毕竟这一部分的代码都是我抄的,我只调了样式,没办法,只能接着搜了呗(写代码是不可能的,这辈子都不可能的,只能靠着CV大佬的代码勉强度日的样子)。
经过
在搜了两个小时之后毫无所获,然后脑海里突然闪过一个念头:
既然不能用js那么麻烦,即使改也只是用两个setTimeout替换一个setInterval ,为啥不能用css呢,即使页面卡死了,也不影响css动画啊,毕竟这两个家伙都不在一个线程里面。
结果
于是我在脑海里面构思了一下,
首先克隆第一个盒子,把它放在最后
然后transform父盒子,当走到最后一个的时候转到显示第二个盒子那里
如下图所示:
其中的原理和其他大佬写的是一致的,我就不多废话了,我就说说不一样的部分
既然是css动画,那我就先把css放出来
.is-animating{
transition: all 0.8s;
}
具体操作部分如下所示
- 第一步:初始化内容,html如下
<div id="container">
<div class="button">
<div class="pre"></div>
<div class="next"></div>
</div>
<ul class="list is-animating" style="height: 400px;">
<li>0<img src="../img1.image"></li>
<li>1<img src="../img2.image"></li>
<li>2<img src="../img3.image"></li>
<li>3<img src="../img4.image"></li>
</ul>
</div>
主要js如下
const width = 500// 图片的宽度
const lists = document.querySelector(".list")
- 第二步:具体操作,每向前走一步,元素的 transform 属性值 translateX 都要减去一张图片的宽度,直到最后一张
const left = -current * width
lists.style.transform = `translateX(${left}px)`;
- 第三步:增加判断,当走到最后一个的时候,将动画效果去除,并将 translateX 的值改为0,之后再添加动画,再将 translateX 改为指定位置,逻辑图如下
重点来了,此时要加一个延时器,让translateX(0px)走完,否则会出现下面这种状况导致无缝轮播失败
为了避免这种状况,需要加一个延时,等待上一步的translate走完,核心代码如下:
lists.classList.remove("is-animating")
lists.style.transform = `translateX(${-max * width}px)`;
setTimeout(() => {
lists.classList.add("is-animating")
translate(current)
handleDot(current)
}, 0)
加上之后就正常了,如下图
以上就是本次分享的全部内容了,如果有更好的方法去实现的,欢迎拍砖!