我正在参加「码上掘金挑战赛」详情请看:码上掘金挑战赛来了!\
前言
📞📞大家好我是 木瓜 。轮播图很多场景都能应用的到,网站的广告、电商的宣传图等等。平常都用插件一把撸。今天突然对轮播图的实现原理感兴趣,尝试用js手写一个轮播图,帮助巩固加深下js的运用。
代码效果
📢📢顺便说一下,蒜必秒吻😡😡
基本功能
- 自动切换轮播图
- 点击左右箭头切换轮播图
- 点击下方圆点切换轮播图
整体结构与实现
HTML结构
这里的HTML大体分为四部分
- 最外层的盒子banner作为主体
- 两个arrow a标签作为箭头
- ul轮播图
- 以及ol小圆点
<div class="banner">
/*左右箭头 这里用两个a标签显示,同时限制a标签的默认跳转*/
<a href="javascript:;" class="arrow-l"><</a>
<a href="javascript:;" class="arrow-r">></a>
/* 轮播图主体*/
<ul class="slider">
<li>
<a href="#"><img src="https://t7.baidu.com/it/u=1819248061,230866778&fm=193&f=GIF" alt=""></a>
</li>
<li>
<a href="#"><img src="https://t7.baidu.com/it/u=737555197,308540855&fm=193&f=GIF" alt=""></a>
</li>
<li>
<a href="#"><img src="https://t7.baidu.com/it/u=1297102096,3476971300&fm=193&f=GIF" alt=""></a>
</li>
<li>
<a href="#"><img src="https://t7.baidu.com/it/u=12235476,3874255656&fm=193&f=GIF" alt=""></a>
</li>
<li>
<a href="#"><img src="https://t7.baidu.com/it/u=1700588201,792130339&fm=193&f=GIF" alt=""></a>
</li>
</ul>
/*轮播图下方小圆点*/
<ol class="cirbox">
</ol>
<input type="text" value="几页"><button>确定</button>
</div>
CSS部分
- banner盒子作为展示主体,设置
overflow: hidden - ul设置6倍于banner的宽度,同时使li float存放banner图
- 左右箭头用a标签
* {
margin: 0;
padding: 0;
}
.banner {
margin: 100px auto;
position: relative;
width: 720px;
height: 455px;
/*border: 1px solid #eee;*/
overflow: hidden;
}
.banner ul {
position: absolute;
height: 455px;
width: 600%;
left: 0;
top: 0;
}
.focus ul li {
height: 455px;
width: 720px;
list-style: none;
float: left;
color: white;
}
.banner ul li img {
width: 100%;
height: 100%;
}
.banner .arrow-l,
.banner .arrow-r {
display: none;
width: 24px;
height: 40px;
position: absolute;
opacity: .5;
top: 50%;
z-index: 2;
background-color: gray;
text-align: center;
line-height: 40px;
font-size: 25px;
color: white;
text-decoration: none;
}
.banner .arrow-r {
right: 0px;
}
.cirbox {
position: absolute;
bottom: 10px;
width: 100%;
text-align: center;
height: 15px;
display: inline-block;
height: 15px;
width: 100%;
/*background: rgba(100, 100, 100, 0.5);*/
border-radius: 7px;
font-size: 0;
/*不加这一句,会使li在ul中向下偏移*/
}
.cirbox li {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
background: #fff;
cursor: pointer;
margin: 10px;
}
.cirbox .active {
background: red;
}
需要注意的事项
-
图片的宽,高度要和
slider中的li标签, 以及div.banner的宽,高度一致。 -
img的宽度为(图片数目+1)*每张图片的宽度。 -
div
.banner部分使用overflow:hidden隐藏slider超出的部分,确保每次该区域只能显示一张图片。 -
css部分主要弄明白轮播图的实现是通过设置ul的left值以及div盒子的overflow:hidden来控制轮播的展示,这里不再赘述。
JS部分(功能实现)
左右按钮切换轮播图
是通过控制ul的left值来实现显示某张图片,但是不能直接改变left值,需要逐渐改变left来实现切换效果。这里我们定义一个动画函数animate来逐渐改变ul的left值,实现切换的动画效果。
function animate(obj, target, callback) { //参数为对象和预期目标
clearInterval(obj.timer);
obj.timer = setInterval(function() { //为不同的对象定时器赋予不同的名字
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step); //注意写在里面
if (obj.offsetLeft == target) { //清除动画,原理是如果盒子的左边距大于target,清除定时器
clearInterval(obj.timer);
if (callback) {
callback();
}
}
obj.style.left = obj.offsetLeft + step + 'px'; //利用定时器的原理使盒子向右移动,
}, 15);
}
左右按钮的click事件,这里左右箭头展示与否是通过控制鼠标是否经过focus盒子
var focus = document.querySelector('.focus'); //banner轮播图展示主体
var arrow_l = document.querySelector('.arrow-l'); //banner轮播图左箭头
var arrow_r = document.querySelector('.arrow-r'); //banner轮播图右箭头
//鼠标经过显示左右按钮,关闭定时器
focus.addEventListener('mouseenter', function () {
arrow_l.style.display = 'block';
arrow_r.style.display = 'block';
clearInterval(timer);
});
//离开隐藏按钮,开启定时器
focus.addEventListener('mouseleave', function () {
arrow_l.style.display = 'none';
arrow_r.style.display = 'none';
timer = setInterval(function () {
arrow_r.click(); //手动调用右边按钮点击事件
}, 2000);
})
当图片从最后一张切换回到第一张时,这时就不能通过改变ul的left值来实现滚动的效果,于是克隆第一张图片至列表尾部,当展示完最后一张图片时,继续滚动到克隆的第一张,然后将ul的left值置为0。
这时候展示的极快,会让人在无缝滚动。实际上是克隆第一个节点滚动,然后迅速把ul的left =0来继续滚动。
if (num == ul.children.length - 1) { //指示器,当num == ul.children.length - 1,此时走到了clone
ul.style.left = 0; //重新回到第一张图片,计数器重新开始
num = 0;
}
🎪🎪下面是完整的箭头click的事件代码(左右箭头代码同理,不同的是需要改变的left值)
//无缝滚动,深克隆ul里第一个li,在for外,不会增加小圆点的长度
var firstImg = ul.children[0].cloneNode(true);
ul.appendChild(firstImg);
var num = 0; //right按钮计算移动距离的索引
var circle = 0; //小圆点计数器
// console.log(ul.children.length - 1);
//右边按钮的功能
arrow_r.addEventListener('click', function () {
if (num == ul.children.length - 1) { //指示器,当num == ul.children.length - 1,此时走到了clone
ul.style.left = 0; //重新回到第一张图片,计数器重新开始
num = 0;
}
num++;
circle++;
for (var i = 0; i < ol.children.length; i++) { //排他
ol.children[i].className = '';
}
if (circle == ol.children.length) { //走到clone 复原成第一个
circle = 0;
}
//console.log(circle);
ol.children[circle].className = 'active';
animate(ul, -num * focus.offsetWidth);
});
//左边按钮的功能
arrow_l.addEventListener('click', function () {
if (num == 0) {
num = ul.children.length - 1; //
ul.style.left = -num * focus.offsetWidth + 'px';
}
num--;
circle--;
for (var i = 0; i < ol.children.length; i++) { //排他,可以封装成一个函数
ol.children[i].className = '';
}
if (circle < 0) {
circle = ol.children.length - 1; //当circle小于0的时候,快速跳到最后一张图
}
ol.children[circle].className = 'active';
animate(ul, -num * focus.offsetWidth);
});
自动滚动的实现
🏡原理就是开启一个定时器,调用右边箭头的click事件来实现滚动。
🏡当鼠标移动到展示主体,关闭定时器,显示按钮。
🏡当鼠标移出取展示主体,开启定时器,隐藏按钮。
//自动播放图片
var timer = setInterval(function () {
arrow_r.click(); //手动调用右边按钮点击事件
}, 2000);
动态添加小圆点
🚛根据图片li的个数动态创建小圆点,同时根据索引动态为小圆点添加active的css类,实现小圆点与图片的同步。
var ul = document.querySelector('ul');
//console.log(ul.children.length);
var ol = document.querySelector('.cirbox');
//动态创建元素li(轮播图的小圆点)
for (var i = 0; i < ul.children.length; i++) {
var lis = document.createElement('li');
lis.setAttribute('index', i); //设置自定义属性li的索引index
ol.appendChild(lis); //添加到ol后
ol.children[0].className = 'active';
};
点击小圆点切换轮播图
🕵️♂️给每个小圆点绑定了click事件,同时使其它小圆点的css类置空。切换轮播图原理与左右箭头切换的一致,这里不再赘述。
lis.addEventListener('click', function () {
for (var i = 0; i < ol.children.length; i++) { //ol li 排他思想
ol.children[i].className = '';
}
var index = this.getAttribute('index');
num = index;
circle = index;
this.className = 'active';
var target = -index * focus.offsetWidth; //点击轮播图的下面的li 向左移动的距离 = index * focus 的距离
animate(ul, target);s
});
最后
🎉🎉好了,到这里一个简易轮播图已经搭建完成。大致原理也已经叙述。技术不精,如果其中有错误希望各位大佬指教。
推荐的轮播图插件
🎃轮播图嘛,还是直接使用插件来的快。这里给大家推荐一个好用的插件