现在很多网站都会用到轮播图效果,轮播图的应用会给你的网站增色不少,本文将一步步带你用原生JavaScript捣鼓出一个轮播图,如果有不正确的地方希望指出,一起交流讨论,先来看下轮播图用到的基本知识点:
1.绝对定位与相对定位
2.overflow: hidden;
3.闭包

HTML布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>js轮播图效果</title>
</head>
<body>
<div id="banner">
<ul class="list" style="left: -600px">
<li>
<img src="5.jpg" alt="第五张">
</li>
<li>
<img src="1.jpg" alt="第一张">
</li>
<li>
<img src="2.jpg" alt="第二张">
</li>
<li>
<img src="3.jpg" alt="第三张">
</li>
<li>
<img src="4.jpg" alt="第四张">
</li>
<li>
<img src="5.jpg" alt="第五张">
</li>
<li>
<img src="1.jpg" alt="第一张">
</li>
</ul>
<div class="buttons">
<span class="on"></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<a href="javascript:;" class="arrow" id="prev">&lt;</a>
<a href="javascript:;" class="arrow" id="next">&gt;</a>
</div>
</body>
</html>

一共有 5 张图片参与轮播,但我们布局里却用了7张图片,这是为了实现无缝连接,即播放到第五张的时候,紧接着第一张。
5个span标签即 5 个小圆点,用来指示当前为第几张图片。
两个a标签用来进行上一张和下一张的点击。
这里给ul设置 left: -600px; 是为了正确地显示第一张图片,而不是显示第五张。

CSS代码

建立了基本的页面布局后,首先重置下css,如下:

1
2
3
4
5
6
7
8
9
10
*{
margin: 0;
padding: 0;
}
li{
list-style: none;
}
a{
text-decoration: none;
}

接着,我们给 id 为 banner 的容器设置宽度为 600px,高度为 400px,给它设置一个 overflow 为 hidden.这个属性可以将超出容器宽高的部分隐藏掉,原理是将 7 张图片放在同一行上,然后只保留一张,把其余的图片 hidden 掉,给父容器设置相对定位,在让 7 张图片相对于父容器进行绝对定位,于是便可以通过 style.left 属性来控制图片的更换了。

1
2
3
4
5
6
7
#banner{
width: 600px;
height: 400px;
position: relative;
overflow: hidden;
margin: 0 auto;
}

图片相对父容器绝对定位,z-index显示层级,这里为1。

1
2
3
4
5
6
.list{
width: 4200px;
height: 400px;
position: absolute;
z-index: 1;
}

使用浮动让7张图片排成一排:

1
2
3
4
5
.list li img{
width: 600px;
height: 400px;
float: left;
}

接下来设置5个小圆点的样式,依然使用绝对定位将它们放在图片正下方并给第一个圆点设置一个 .on 类指示当前轮播图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.buttons{
position: absolute;
bottom: 10px;
right: 250px;
z-index: 2; //这里为2,意味着层级比刚刚的图片容器1要高,所以圆点会覆盖在图片的上方
}
.buttons span{
margin-left: 5px;
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
background-color: \#fff;
color:white;
cursor: pointer;
}
.buttons .on{
background-color: \#00acec;
}

最后就是前进与后退箭头了,依然如前面一样绝对定位,z-index为2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.arrow{
cursor: pointer;
display: none;
line-height: 38px;
text-align: center;
font-size: 36px;
font-weight: bold;
width: 40px;
height: 40px;
position: absolute;
z-index: 2;
top: 180px;
text-decoration: none;
color: #fff;
}
.arrow:hover{
background: #ececec;
}
#banner:hover .arrow{
display: block;
}
#prev{
left: 10px;
}
#next{
right: 10px;
}

至此,CSS样式已经添加完毕,来看下当前的静态效果:

效果图
效果图

JavaScript代码

页面布局与样式设置好后,使用 js 来添加轮播逻辑:
首先我们获取到 list 容器,通过控制它的left值来轮播图片,即每次点击触发一个 onclick 事件,将 list 的 left 值加/减上 600(1张图片的宽度),这里特别注意的是,当 left
的值向右一直加到 -3600px 时,也就是此时播到我们用来无缝衔接的第 1 张图片,这个时候就要手动将 left 值更改为 -1200 ,也就是说,在点击则调回到第 1 张图片播放,这样每次播到最后一张图片的时候,它就会跳回到第 2 张图片,这样就能循环下去;同理,当点击向左的按钮时,left值不断地在往回退,一直到 left 为 0,此时已经到最左边的第一张了,我们把
它的值重置到第倒数第二张图片那里,这样就又继续循环下去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var list = document.querySelector('.list');
var prev = document.getElementById('prev');
var next = document.getElementById('next');
next.onclick = function(){
next_pic();
};
prev.onclick = function(){
prev_pic();
};
function next_pic(){
var newleft;
if(list.style.left === '-3600px'){
newleft = -1200;
}else{
newleft = parseInt(list.style.left)-600;
}
list.style.left = newleft + 'px';
}
function prev_pic(){
var newleft;
if(list.style.left === '0px'){
newleft = -2400;
}else {
newleft = parseInt(list.style.left) + 600;
}
list.style.left = newleft + 'px';
}

看下效果:

效果图
效果图

现在图片已经可以手动点击播放了,我们希望能自动播放,只需添加下面这个函数:

1
2
3
4
5
6
7
8
var timer;
function autoplay(){
clearInterval(timer);
timer = setInterval(function(){
next_pic();
},2000);
}
autoplay();

现在它可以自动播放了,效果是这样子:

效果图
效果图

此时在给它添加一个函数,鼠标移上去的时候停止播放,当鼠标移出的时候就让它自动播放:

1
2
3
4
5
6
var banner = document.getElementById('banner');
function stop(){
clearInterval(timer);
}
banner.onmouseover = stop;
banner.onmouseout = autoplay;

做到现在,我们发现当图片轮播的时候,下方的小圆点没有跟着变,现在我们来改变它。实现原理是设置一个全局的变量 index,当点击右箭头时,在 next_pic 函数里让 index++;当点击左箭头时,在 prev_pic 函数里让 index–,然后设置当前 index 的圆点的 class 为 on,同样,当 index++ 到 5 时,要归为 0 从头开始;当 index– 到 0 时,归为 4 使其向左继续递减,代码如下:

1
2
3
4
5
6
7
8
var index = 0;
var buttons = document.querySelector('.buttons').getElementsByTagName('span');
function showButton(){
for(var i = 0;i<buttons.length;i++){
buttons[i].className = "";
}
buttons[index].className = "on";
}

在 next_pic() 函数里添加:

1
2
3
4
5
index++;
if(index > 4){
index = 0;
}
showButton();

在 prev_pic() 函数里添加:

1
2
3
4
5
index--;
if(index < 0){
index = 4;
}
showButton();

此时小圆点就可以跟着图片的改变而改变当前圆点的颜色了。
最后一个功能就是,当点击小圆点时,相应的图片也要跟着变化,这里可以用闭包来实现,当点击小圆点时,通过比较当前圆点的 index 值与全局变量 index 来重新计算 left 值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
for (var i = 0;i<buttons.length;i++){
(function(i){
buttons[i].onclick = function () {
var curr = index - i;
if(index === 4 && parseInt(list.style.left)!==-3000){
curr = curr - 5;
}

if(index === 0 && parseInt(list.style.left)!== -600){
curr = 5 + curr;
}
list.style.left = (parseInt(list.style.left) + curr * 600)+"px";
index = i;
showButton();
}
})(i);
}

最终就实现了一个轮播图的效果:

效果图
效果图

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>js轮播图效果</title>
<style>
*{
margin: 0;
padding: 0;
}
li{
list-style: none;
}
a{
text-decoration: none;
}
#banner{
width: 600px;
height: 400px;
position: relative;
overflow: hidden;
margin: 0 auto;
}
.list{
width: 4200px;
height: 400px;
position: absolute;
z-index: 1;
}
.list li img{
width: 600px;
height: 400px;
float: left;
}
.buttons{
position: absolute;
bottom: 10px;
right: 250px;
z-index: 2;
}
.buttons span{
margin-left: 5px;
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #fff;
color:white;
cursor: pointer;
}
.buttons .on{
background-color: #00acec;
}
.arrow{
cursor: pointer;
display: none;
line-height: 38px;
text-align: center;
font-size: 36px;
font-weight: bold;
width: 40px;
height: 40px;
position: absolute;
z-index: 2;
top: 180px;
text-decoration: none;
color: #fff;
}
.arrow:hover{
background: #ececec;
}
#banner:hover .arrow{
display: block;
}
#prev{
left: 10px;
}
#next{
right: 10px;
}
</style>
</head>
<body>
<div id="banner">
<ul class="list" style="left: -600px">
<li>
<img src="5.jpg" alt="">
</li>
<li>
<img src="1.jpg" alt="">
</li>
<li>
<img src="2.jpg" alt="">
</li>
<li>
<img src="3.jpg" alt="">
</li>
<li>
<img src="4.jpg" alt="">
</li>
<li>
<img src="5.jpg" alt="">
</li>
<li>
<img src="1.jpg" alt="">
</li>
</ul>
<div class="buttons">
<span class="on"></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<a href="javascript:;" class="arrow" id="prev">&lt;</a>
<a href="javascript:;" class="arrow" id="next">&gt;</a>
</div>

<script>
'use strict';
window.onload = function () {
var banner = document.getElementById('banner');
var list = document.querySelector('.list');
var prev = document.getElementById('prev');
var next = document.getElementById('next');
var buttons = document.querySelector('.buttons').getElementsByTagName('span');
var timer;
var index = 0;
next.onclick = function(){
next_pic();
};
prev.onclick = function(){
prev_pic();
};
function next_pic(){
var newleft;
if(list.style.left === '-3600px'){
newleft = -1200;
}else{
newleft = parseInt(list.style.left)-600;
}
list.style.left = newleft + 'px';
index++;
if(index > 4){
index = 0;
}
showButton();
}
function prev_pic(){
var newleft;
if(list.style.left === '0px'){
newleft = -2400;
}else {
newleft = parseInt(list.style.left) + 600;
}
list.style.left = newleft + 'px';
index--;
if(index < 0){
index = 4;
}
showButton();
}
function autoplay(){
clearInterval(timer);
timer = setInterval(function(){
next_pic();
},2000);
}
function stop(){
clearInterval(timer);
}
autoplay();
banner.onmouseover = stop;
banner.onmouseout = autoplay;

function showButton(){
for(var i = 0;i<buttons.length;i++){
buttons[i].className = "";
}
buttons[index].className = "on";
}

for (var i = 0;i<buttons.length;i++){
(function(i){
buttons[i].onclick = function () {
var curr = index - i;
if(index === 4 && parseInt(list.style.left)!==-3000){
curr = curr - 5;
}
//和使用prev和next相同,在最开始的照片5和最终的照片1在使用时会出现问题,导致符号和位数的出错,做相应地处理即可
if(index === 0 && parseInt(list.style.left)!== -600){
curr = 5 + curr;
}
list.style.left = (parseInt(list.style.left) + curr * 600)+"px";
index = i;
showButton();
}
})(i);
}
};
</script>
</body>
</html>