轮播图功能分析:
- 可以自动循环
- 点击轮播图下面的上一页下一页按钮,轮播图也可以进行播放
- 当鼠标放在轮播图上时,停止播放,当鼠标离开时,则继续播放
它涉及到了两个定时器: 第一个定时器是用更换图片的,第二个定时器用来每隔15ms往前移动图片10px。
页面样式实现
<div id="box">
<ul class="pic_list">
<!-- <li class="item"><img class="pic" src="img/img4.jpg" alt=""></li> -->
<li class="item"><img class="pic" src="img/img2.jpg" alt=""></li>
<li class="item"><img class="pic" src="img/img3.jpg" alt=""></li>
<li class="item"><img class="pic" src="img/img4.jpg" alt=""></li>
<!-- <li class="item"><img class="pic" src="img/img2.jpg" alt=""></li> -->
</ul>
</div>
<div class="btn">
<button id="prev">前一张</button>
<button id="next">后一张</button>
</div>
设定轮播三张图片:
- box用于定于轮播框的大小,宽400px、高300px,并且水平居中
- pic_list定义宽400%、高300px,能够放入所有的图片
- item将图片浮动起来,所有图片放在了一行显示
#box {
width: 400px;
height: 300px;
position: relative;
margin: 0 auto;
overflow: hidden;
}
.pic_list {
list-style: none;
width: 500%;
height: 300px;
position: relative;
padding: 0;
margin: 0;
top: 0px;
}
.pic {
width: 400px;
height: 300px;
padding: 0;
margin: 0;
}
.item {
float: left;
}
.btn {
margin: 10px auto;
width: 150px;
}
功能分块介绍
1. 初始化:
获取pic_list,用于通过style上的left改变位置,点击下一张的话,向左移动,点击上一张,则向右移动。
let imags = document.querySelector('.pic_list');//同样移动图片
获取轮播图有几张图片
let length = document.querySelectorAll('.item').length;//减去在头和尾部加的两张图片
初始化列表最开始的位置
imags.style.left = '0' + 'px';//初始化列表最开始的位置
这是一些参数,time
是第一个定时器(用于跳到下一张,每隔2400ms便跳转到下一张)。time2
第二个定时器(图片每隔15ms便向左移动10px)。distance
记录图片一共移动的距离。index
记录图片当前的索引
let time = null, time2 = null, distance = 0, index = 1;
2. init函数,轮播图中的一些鼠标事件都会在这里定义。
- 获取页面元素
const box = document.querySelector('#box');
const pre = document.querySelector('#prev');
const next = document.querySelector('#next');
- 点击上一页,触发动画,将值1传入(用来标识我要看上一张)
- 点击下一页,触发动画,将值2传入(用来标识我要看下一张)
pre.onclick = function () {
animate(1);
}
next.onclick = function () {
animate(2);
}
- 鼠标移动到图上时,动画就会停止。用到的监听函数,并清除定时器
box.addEventListener('onmouseenter', function () {
clearInterval(time);//鼠标进入清除定时器
}, 2500);
- 鼠标移开图片上时,动画会继续。
box.addEventListener('onmouseleave', function () {
// 鼠标离开开启定时器
time = setInterval(function () {
// clearInterval(time2)
animate(2);
}, 2500)
})
3. 动画函数
- 首先就要判断time2是否存在,如果还没到时间,就不会去执行这个动画
- 定义一个setInterval
- 判断是前进还是后退
- distance就在这里用到了,用来记录这个图片前进了多少,后退了多少
- 图片要移动咯。
imags.style.left = (parseInt(imags.style.left) + step) + 'px'
- 判断当前distance是否已经移动了他自己的宽度,到下一张图片了。
- 是的话,清除time2,并置为Null。根据传入的Num值,index加一或者减一。
- 此时有两种临界情况:
- 如果index移动到了最后一张图片的后面(下标从1开始)。index跑到第1个,然后图片的位置移动到第一张图片的位置上。
- 如果index移动到了第一张图片的前面,index就对应的最后一张图片,图片的位置移动到最后一张图片的位置上。
function animate(num) {
console.log(time2)
if (!time2) {
time2 = setInterval(function () {
let step = num === 1 ? 10 : -10;
distance += Math.abs(step);
imags.style.left = (parseInt(imags.style.left) + step) + 'px'
if (distance >= 400) {
clearInterval(time2)//重新计时
time2 = null;
distance = 0;//重新计算距离
if (step > 0) index -= 1;//点击pre,index图片列表就-1
if (step < 0) index += 1;//点击next,index图片列表就+1
if (index > length) {//已经滑到图片列表的尾部
index = 1;
imags.style.left = 0 + 'px';
} else if (index < 1) {
index = length;
imags.style.left = (-400) * (length - 1) + 'px';
}
console.log(index)
}
}, 15)
}
}
这样写其实有点bug:
小bug
这里回到页面样式这部分,一开始我很不理解为什么要在头和尾处添加两张重复的图片,为什么要添加?作用是啥呢?后来我就把他删了,也能实现出来。但是出现了这样的bug,这时候才明白添加这两张图片是很有必要的。比如说当图片运行到最后一张的时候,此时index=3,还会再继续往前进,但是前面是空白,当移动400px的时候,此时index=4,才会进入临界条件,imags的位置重新赋值,移动到第一个图片但是这段时间的空白怎么办?确实可以从最后一个移动到第一个,但是在移动的过程中会有空白出现,此时在图片列表左右添加上两张图片就不会出现这种情况了,下面的代码,完美的解决了这个问题:
//这一块记得修改哈
let length = document.querySelectorAll('.item').length - 2;
imags.style.left = '-400' + 'px';//初始化列表最开始的位置
function animate(num) {
if (!time2) {
time2 = setInterval(function () {
let step = num === 1 ? 10 : -10;
distance += Math.abs(step);
imags.style.left = (parseInt(imags.style.left) + step) + 'px'
if (distance >= 400) {
clearInterval(time2)//重新计时
time2 = null;
distance = 0;//重新计算距离
if (step > 0) index -= 1;//点击pre,index图片列表就-1
if (step < 0) index += 1;//点击next,index图片列表就+1
if (index > length) {//已经滑到图片列表的尾部
index = 1;
imags.style.left = -400 + 'px';
} else if (index < 1) {
index = length;
imags.style.left = (-400) * length + 'px';
}
console.log(index)
}
}, 15)
}
}