轮播图现有成熟的插件非常多,但做为一名学习中的想要成为前端开发的小伙伴们来说,自己动手实现一个轮播图,还是很锻炼的,实现完成后,也是很有成就感的。下面,我们来实现一个简单的轮播图吧。
目录
1 HTML + CSS3布局
2 为什么要多放一个图片?
3 滚动实现
3.1 初始化变量
3.2 初始化页面元素
3.3 3秒自动滚动一次
3.4 点击按钮到达目标图片
1 HTML + CSS3布局
轮播图中,HTML布局有那么几个重要点:
- 外层的div元素,要设定要宽高,并且overflow:hidden;意思就是轮播图,其实是几张图片横排起来的,会非常长,所以需要将提前设定好的宽高以外的内容限制住。不能超出这个范围,超出就得让用户看不见。不过前端嘛,经常干这种事,怎么把元素隐藏起来。其实是有的,但不能让用户看见。
- 里层有一个div元素(或者其他ul元素也行),重点就是装这些横排起来的非常多的图片元素,这个里层的div元素呢,是可以很长的。外层的父元素已经overflow:hidden了,放心,多余的是看不见的。
- 让这些图片元素横排起来。不过轮播图嘛,有可点击的,有不可点击的。这一小节,我们先来实现一个纯图片的,不可点击的。什么是可点击的?你看那些正经网站,谁纯展示一个轮播图啊,那么大那么重要的区域,肯定是得诱导用户去点击你这个非常有价值的轮播图啊。
<div id="box-t">
<div class="box-imgs" id="boxImgs" style="left:0;">
<img class="tup" src="../images/1.jpg" alt="" />
<img class="tup" src="../images/2.jpg" alt="" />
<img class="tup" src="../images/3.jpg" alt="" />
<img class="tup" src="../images/4.jpg" alt="" />
<img class="tup" src="../images/5.jpg" alt="" />
<img class="tup" src="../images/1.jpg" alt="" />
</div>
<div class="box-t-y">
<p class="box-t-x" index="1" onclick="handleBtns(0)"></p>
<p class="box-t-x" index="2" onclick="handleBtns(1)"></p>
<p class="box-t-x" index="3" onclick="handleBtns(2)"></p>
<p class="box-t-x" index="4" onclick="handleBtns(3)"></p>
<p class="box-t-x" index="5" onclick="handleBtns(4)"></p>
</div>
</div>
#box-t{
overflow: hidden;
position: relative; /*设置相对定位*/
height: 400px;
}
.box-imgs {
position: absolute;
left: 0;
top: 0;
display: flex;
width: 6000px;
height: 400px;
}
#box-t img{
width:1000px;
height:400px;
}
.tup{
display:block;
}
.box-t-y{
position:absolute; /*给按钮添加绝对定位*/
right:45%;
bottom:0; /*下边距为0*/
}
.box-t-x{
width:20px;
height:20px;
display: inline-block; /*不独占一行的块级元素*/
opacity:0.7; /*设置透明度*/
border:1px solid #fff; /*边框为1像素白色实线*/
border-radius:10px; /*实现椭圆效果*/
margin-right:10px;
cursor: pointer;
}
.box-t-x:hover, .box-t-x-hover {
background: #FC9;
}
2 为什么要多放一个图片?
本来轮播图组件中是5张图片轮播的,为什么要多放一张,看HTML元素里是6张图片元素呢?
这是因为第5张图片播放完了以后,其实该播放第一张图片了。但如果只有5张图片的话,什么时候播放第一张图片,这需要一个时机。第5张播放完了,按理说应该继续并且顺序的播放第一张,但第一张如果在最左边的话,直接跳动到第一张,或者滚动很长,从第5张到第1张,怎么弄都很不好看。
这个时候,放第6张图片,而第6张图片存放的就是第一张图片。这样让轮播图组件顺滑的从第5张滚动到第6张,但用户看来,这其实是顺滑的滚动到了第一张图片上。当轮播图滚动到了第6张图片后,因为有3秒的等待期,这个时候,再悄么声的把图片换为第一张,用户其实是无感知的。
3 滚动实现
3.1 初始化变量
let intervalTimer = null; // 初始化定义滚动定时
let scrollIndex = 0;
let boxImgs = document.getElementById('boxImgs');
let btns = document.querySelectorAll('.box-t-x');
滚动,比如几秒滚动一次,比如每次滚动需要多久的时间,比如电脑刷新频率是一秒多少次才能不显得卡,这些都需要一定的定时任务来完成。
然后既然是轮播,那么一定随时需要知道当前滚动到第几张了,下面的按钮是第一个当前需要高亮显示。这些变量都做一个初始化。
3.2 初始化页面元素
// 初始化页面元素
function initImgs() {
scrollIndex = 0;
boxImgs.style.left = `0`;
btns.forEach((item) => {
item.className = 'box-t-x';
})
btns[0].className = 'box-t-x box-t-x-hover';
}
initImgs();
说是轮播图在滚动,其实是子div距离左边的距离,一直在发生变化。而且父元素已经使用了overflow:hidden。这样一来,不管是左边超出,或者是右边超出,用户都是看不到的。但这个长长的元素已经超出去了。
那么我们初始化的时候呢,设定这个子div距离左边的距离为0,意思就是初始化的时候,默认是第一张图片显示,而且图片的宽度和最外层div的宽度保持一致,这样一张图就能占满整个区域了,用户看见的就是一张图一个区域。
然后我们给底部按钮初始化一下,给第1个按钮加个选中样式,让用户知道,当前是第一张。
3.3 3秒自动滚动一次
// 3秒自动滚动
function autoScroll() {
intervalTimer = setInterval(() => {
let onecIndex = 1;
let onecScroll = setInterval(() => {
boxImgs.style.left = `-${(scrollIndex*1000) + 100*onecIndex}px`;
if (onecIndex >= 10) {
window.clearInterval(onecScroll);
onecScroll = null;
// 一次移动结束后
scrollIndex++;
if (scrollIndex >= 5) {
initImgs();
} else {
// 底部按钮选中改变
btns.forEach((item) => {
item.className = 'box-t-x';
})
btns[scrollIndex].className = 'box-t-x box-t-x-hover';
}
}
onecIndex++;
}, 50)
}, 3000)
}
autoScroll();
这里采用了3秒自动滚动一次的方式,我们让之前初始化的变量scrollIndex自动累加,当要超出图片长度的时候,再将这个值恢复为0。
3.4 点击按钮到达目标图片
function handleBtns(index) {
// 如果是点击当前的,那么无效
if (index === scrollIndex) {
return;
}
// 停止自动滚动
window.clearInterval(intervalTimer);
intervalTimer = null;
// 给选中按钮加样式
btns.forEach((item) => {
item.className = 'box-t-x';
})
btns[index].className = 'box-t-x box-t-x-hover';
let boxImgsLeft = Number(boxImgs.style.left.slice(0, -2));
let toLeft = -index*1000;
let scrollLeftAbs = Math.abs(toLeft - boxImgsLeft);
// 需要频繁移动的次数
let scrollNum = scrollLeftAbs/100;
let onecIndex = 1;
let onecScroll = setInterval(() => {
// 向左滚动
if (index > scrollIndex) {
let newLeft = boxImgsLeft - 100*onecIndex;
boxImgs.style.left = `${newLeft}px`;
}
// 向右滚动
if (index < scrollIndex) {
let newLeft = boxImgsLeft + 100*onecIndex;
boxImgs.style.left = `${newLeft}px`;
}
if (onecIndex >= scrollNum) {
scrollIndex = index;
window.clearInterval(onecScroll);
onecScroll = null;
autoScroll();
}
onecIndex++;
}, 50)
}
当点击按钮的时候,我们需要做如下判断:
- 如果点中的按钮和当前图片是同一张,那么就是无效的;
- 如果点中的按钮索引呢,比当前图片的索引大,索引是啥?就是当前是第几张,从0开始算。如果点中的索引大,那么就让轮播图继续向左滑动;
- 如果点中的按钮索引值,比当前图片索引值小,那么我们就让他向反方向滑动。