今天在网上看到有人说到轮播图。我自己还没写过,所以简单实现一个。
GitHub链接:https://github.com/cyjsysu/mi...
1. 效果
2. 实现方案
我首先想到了三种可能可以实现的方法。
- 设一个div标签,定时更改背景图和链接。
- 设置5个相同的div,分别有不同的背景图。定时更改每个div的display(block/none)。
- 类似2。每次调整div的z-index。
然后就是老规矩,打开B站,有样学样。通过B站的HTML可以发现B站首页的轮播图用的就是第三种方法。
为了进一步熟悉面向对象,我在小项目里用了class。
3. 轮播
这里有5张图片,先使 position: absolute
,不考虑js并且不做特别设置的前提下,显示在上面的是最后一张图。为了让文件开始加载时就显示第一张图,而不是最后一张,我设置第一张图的z-index为1,其余为0。
类的成员变量定义如下。通过设置定时器,让index在0到4变动,每次设置相应div的z-index为++maxZ
即可。比较简单。
class Carousel {
constructor() {
this.index = 0; //当前显示图片索引
this.maxZ = 1; //当前图片最大z-index
this.timer = null; //定时器
}
}
4. 更改图片的小圆点
这个很简单,用事件委托实现即可。给id为trigger的结点绑定一个onclick事件。触发后判断是点击了哪个圆点,再做相应处理即可。
这里我多做了一点。之前在某个著名网站上我对其轮播图的体验非常差,因为我切换了图片后,他的定时器触发,马上又跳转到了下一张。所以我这里点击后会取消掉现有的定时器,处理完毕后再重置。这就避免了以上问题。
5. 碰到的坑
5.1 用class创建对象时this的指向问题
使用回调函数时出现问题。像下面这种情况,this指向window。
this.timer = setInterval(function (){}, 1000);
可使用bind解决问题。
this.timer = setInterval(function (){}.bind(this), 1000);
5.2 代码执行时机存在问题
开始时,使用document.getElementById
会返回undefined。我认为问题是body未加载完就执行了js代码。用window.onload
即可解决问题。
6. 全部代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>carousel</title>
<style>
#carousel {
width: 800px;
height: 450px;
position: relative;
margin: 0 auto;
}
#slide {
width: 100%;
height: 100%;
position: absolute;
}
#slide .item {
width: 100%;
height: 100%;
position: absolute;
z-index: 0;
}
#slide .item img {
width: 100%;
height: 100%;
}
#trigger {
width: 260px;
height: 40px;
/*background-color: red;*/
left: 500px;
top: 400px;
position: absolute;
z-index: 2147483647;
}
#trigger span {
width: 20px;
height: 20px;
margin-left: 25px;
background-color: white;
border-radius: 50%;
z-index: 2147483647;
display: inline-block;
}
#trigger .on {
background-image: url("./img/吃豆人.png");
background-repeat: no-repeat;
background-size: cover;
background-color: transparent;
transform: scale(1.8);
/*background-color: red;*/
}
</style>
<script>
window.onload = function () {
var carouselObj = new Carousel();
};
class Carousel {
constructor() {
this.index = 0; //当前显示图片索引
this.maxZ = 1; //当前图片最大z-index
this.timer = null; //定时器
this.init(); //初始化
}
init() {
this.setTimer(); //设置定时器
//绑定事件,当点击圆点时跳转到相应图片
var oTrigger = document.getElementById("trigger");
oTrigger.onclick = function (evt) {
clearInterval(this.timer); //先暂停定时器
var oImgItems = document.getElementById("slide").getElementsByClassName("item");
var oTriggerSpan = document.getElementById("trigger").getElementsByTagName("span");
//确定点击的圆点索引
var target = evt.target;
var toIndex = -1;
for (var i = 0; i < oTriggerSpan.length; i++) {
if (oTriggerSpan[i] == target)
toIndex = i;
}
oTriggerSpan[this.index].classList.remove("on");
this.index = toIndex;
oTriggerSpan[this.index].classList.add("on");
oImgItems[this.index].style.zIndex = ++this.maxZ;
this.setTimer(); //恢复定时器
}.bind(this);
}
setTimer() {
clearInterval(this.timer);
//console.log([this.index, this.maxZ]);
this.timer = setInterval(function () {
var oImgItems = document.getElementById("slide").getElementsByClassName("item");
var oTriggerSpan = document.getElementById("trigger").getElementsByTagName("span");
oTriggerSpan[this.index].classList.remove("on");
this.index = (this.index + 1) % oImgItems.length;
oTriggerSpan[this.index].classList.add("on");
oImgItems[this.index].style.zIndex = ++this.maxZ;
}.bind(this), 1000);
}
}
</script>
</head>
<body>
<div id="carousel">
<div id="slide">
<div class="item" style="z-index: 1">
<a href="#">
<img src="./img/蜘蛛侠.jpg" alt="蜘蛛侠">
</a>
</div>
<div class="item">
<a href="#">
<img src="./img/飞屋环游记.jpg" alt="飞屋环游记">
</a>
</div>
<div class="item">
<a href="#">
<img src="./img/小黄人.jpg" alt="小黄人.">
</a>
</div>
<div class="item">
<a href="#">
<img src="./img/宝可梦.jpg" alt="宝可梦">
</a>
</div>
<div class="item">
<a href="#">
<img src="./img/海绵宝宝.jpg" alt="海绵宝宝">
</a>
</div>
</div>
<div id="trigger">
<span class="on"></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
</body>
</html>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。