轮播图在Web前端很常见,现在我也是刚开始学Web。
主要实现轮播图的自动播放,以及点击按钮可以切换对应的图片。
总结一下最近写轮播图的方法和注意点叭~
以下是轮播图的效果,在图上加了图片的序号><
接下来一起开始从头的制作叭!
1. html文件
<body>
<!-- 注意如果还有外层的话记得加上定位,为了offsetLeft的准确 -->
<div class="banner">
<!-- 轮播图的容器 -->
<ul class="slide">
<li>
<a href="#">
<img src="images/0.jpg" alt="">
</a>
</li>
<li>
<a href="#">
<img src="images/1.jpg" alt="">
</a>
</li>
<li>
<a href="#">
<img src="images/2.jpg" alt="">
</a>
</li>
<li>
<a href="#">
<img src="images/3.jpg" alt="">
</a>
</li>
</ul>
<!-- 轮播点的容器 事先无法确定图的个数 所以不写死li的个数 后面通过js自动插入 -->
<ul class="dots"></ul>
</div>
</body>
大致的意思就像下图:
通过很宽的ul(绿色)来装如所有的轮播图li,让li左浮动,使他们都在一行上。然后通过刚好允许一张图片显示的定宽的盒子div(橙色)包在ul的外面,这样,我们通过ul的left来移动ul,然后将div设为overflow:hidden,我们就只能看见一张图片啦~
第一排是left:0,第二排是left:-500px,即将第二个li移入div里。
2. CSS文件
将页面布局成如下效果:
注意测试的时候可以不给div加上overflow:hidden属性,这样会看的更清楚ul是怎么运作的哦~
*{
margin: 0;
padding: 0;
}
body{
background-color: #000;
}
.banner{
position: relative; /*point 1*/
margin: 50px auto;
width: 500px;
overflow: hidden;
}
.slide{
position: relative; /*point 1*/
width: 3000px;
overflow: hidden; /*清除浮动*/
}
.slide li{
float: left;
}
.slide li img{
width: 500px;
}
.dots{
overflow: hidden;
display: inline-block;
position: relative;
left: 50%;
transform: translateX(-50%);
}
.dots li{
/* 这里用浮动的话会有问题,也不太清楚为什么,js的点击事件this不准确 */
display: inline-block; /*point 2*/
cursor: pointer;
width: 10px;
height: 10px;
border-radius: 50%;
background-color: ivory;
margin: 0 4px;
}
.dots .selected{
background-color: lightcoral;
}
CSS的样式自己写就可以,比较简单,但是有几个地方想要特别强调一下,我自己写的时候有几个细节很容易导致错误,这些地方我都在代码上标上了备注!!
-
point 1
首先一定一定一定!!要在ul上加上定位!!
否则当在JS中设置left的值的时候就移动不了,因为left属性是在有position的时候才有意义的。其次!一定一定一定!!要在ul外的每一个父元素都加上定位!!
因为在JS中移动是通过控制offsetLeft属性,而offsetLeft属性和定位息息相关,可以参照https://blog.csdn.net/w390058785/article/details/80461845 这个博客。(当时我不知道这个卡了可久TT) -
point 2
还有一个点是轮播点用的是inline-block,而不能用float:left。
这个我不懂为啥要这样,如果有大佬知道的话,欢迎教教我~
如果我用浮动的话,JS的点击就会不准确,this没法得到对应的li。
3. JS文件
- 首先我们要来实现一个函数,来封装移动ul的功能。
function animate(obj, target, callback)
obj:需要移动的元素,target:移动的目标位置,callback:回调函数
函数的代码如下:
function animate(obj, target, callback) {
obj.timer = setInterval(function () {
step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
if (callback) {
callback();
}
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
这里是通过设置一个定时器来每隔15ms移动一段距离,看起来仿佛是动画一样的效果,然后通过step来设置步长,每次移动的距离都逐渐减小,有一种运动的先快后慢的效果。
step = step > 0 ? Math.ceil(step) : Math.floor(step);
这个是因为step因为使用了除法,会有一些误差,有小数,所以向上下取整。
、
- 完成上面的函数后,我们可以开始写轮播图的JS逻辑啦!
对应的解释,我已经写在了备注里,请放心食用~
// 移动轮播图容器的函数
// obj是移动的对象,即ul;target是移动的目标位置,即ul的left的值;callback是回调函数
function animate(obj, target, callback) {
obj.timer = setInterval(function () {
step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
if (callback) {
callback();
}
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
window.addEventListener('load', function () {
var num = 0;
var banner = document.querySelector('.banner');
var slide = document.querySelector('.slide');
var dots = document.querySelector('.dots');
// 首先动态插入轮播点,插入的个数等于slide里的li的个数
for (var i = 0; i < slide.children.length; i++) {
var dot = document.createElement("li");
dot.setAttribute('index', i);//设置index属性,方便后面点击轮播点,拿到对应的索引
dot.addEventListener('click', function () {
console.log(this);
// 点击轮播点后,改变被点击的点的颜色
// 点击某个轮播点后,将所有点类名设置为空
for (var i = 0; i < dots.children.length; i++) {
dots.children[i].className = '';
}
// 将被点击的点的类名设置为selected
this.className = 'selected';
var index = this.getAttribute('index');
num = index;
console.log(index);
// 取得ul移动的距离,即索引*轮播图的宽度(从0开始),注意这里是向左移动,所以取负的
var target = -index * banner.offsetWidth;
animate(slide, target);
})
dots.appendChild(dot);
}
// 插入完成后,将第一个轮播点设为被选择状态
dots.children[0].className = 'selected';
// 将第一个图克隆,粘贴到slide的最后面,这样最后一张图播放到第一张图时才能平滑向后滑
// 因为是在生成小图标后添加图片,所以自动生成的小图标并不会增多
var first = slide.children[0].cloneNode(true);
slide.appendChild(first);
//设置自动播放,这里的num要配合点击事件的index,保证从被点击的地方继续自动播放
var Timer = setInterval(function () {
//到了最后一张的克隆的图片
if (num == slide.children.length - 1) {
num = 0;
slide.style.left = 0; //设置为第一张图片,然后马上会滑向第二张图片,这样实现无缝连接
}
++num;
var target = -num * banner.offsetWidth;
animate(slide, target);
//改变对应的点
for (var i = 0; i < dots.children.length; i++) {
dots.children[i].className = '';
}
dots.children.className[num % dots.children.length] = 'selected';
}, 3000);
// 鼠标放上停止自动播放
banner.addEventListener('mouseover', function () {
clearInterval(Timer);
Timer = null;
})
// 鼠标离开继续播放
banner.addEventListener('mouseleave', function () {
Timer = setInterval(function () {
//到了最后一张的克隆的图片
if (num == slide.children.length - 1) {
num = 0;
slide.style.left = 0; //设置为第一张图片,然后马上会滑向第二张图片,这样实现无缝连接
}
++num;
var target = -num * banner.offsetWidth;
animate(slide, target);
//改变对应的点
for (var i = 0; i < dots.children.length; i++) {
dots.children[i].className = '';
}
dots.children[num % dots.children.length].className = 'selected';
}, 3000);
})
})
到这里就完成我们的轮播图啦~
第一次写Web的笔记,有什么问题的话欢迎指正~