使用JavaScript实现焦点轮播图

原理

各大网站都使用焦点轮播图来展示自己的图片,如淘宝、京东等。

  1. 焦点轮播图所用技能点:DOM操作、定时器、事件运用、JS动画、函数递归、无限滚动;
  2. 无限滚动实现:包含图片的父级标签要有一个属性overflow:hidden 来隐藏超出自身尺寸的内容;有style:left通过控制left值来实现滚动; 图片列表中要在开始和结束位置添加两张相同的附属图,使图片实现无缝连接。


使用html和css实现静态页面布局

  1. 父容器要承载图片、圆点下标、左右切换箭头,要让超出部分隐藏overflow:hidden、定位为position:relative
  2. 图片的div要添加定位:position:absolute让它基于父容器relative,z-index:1使图片堆叠在第一层上;
  3. 圆点下标和左右切换箭头设置z-index:2position:absolute,让其覆盖在图片上;
  4. 左右切换箭头在初始状态下设置为隐藏display:none,鼠标移上图片时使其显示display:block,鼠标移到箭头上时改变透明度RGBA,使箭头颜色加深;

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>焦点轮播图</title>
<link rel="stylesheet" type="text/css" href="css/焦点轮播图.css">
</head>
<body>
<div id="container">
<div id="list" style="left: -600px">
<img src="images/5.jpg" alt="5"> <!-- 附属图实现无缝的滚动 -->
<img src="images/1.jpg" alt="1">
<img src="images/2.jpg" alt="2">
<img src="images/3.jpg" alt="3">
<img src="images/4.jpg" alt="4">
<img src="images/5.jpg" alt="5">
<img src="images/1.jpg" alt="5">
</div>
<div id="buttons">
<span index="1" class="on"></span>
<span index="2"></span>
<span index="3"></span>
<span index="4"></span>
<span index="5"></span>
</div>
<a href="javascript:;" id="prev" class="arrow">&lt;</a>
<a href="javascript:;" id="next" class="arrow">&gt;</a>
</div>
<script type="text/javascript" src="js/焦点轮播图.js"></script>
</body>
</html>

CSS代码

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
*{
margin: 0;
padding: 0;
text-decoration :none;
}
body{
padding: 20px;
}
#container{
width: 600px;
height: 400px;
position: relative;
border: 3px solid #333;
overflow: hidden;
}
#list{
height: 400px;
width: 4200px;
position: absolute;
z-index: 1; /*设置元素的堆叠顺序*/
}
#list img{
float: left;
}
#buttons{
height: 10px;
width: 100px;
z-index: 2;
bottom: 20px;
left: 250px;
position: absolute;
}
#buttons span {
cursor: pointer; /*规定要显示的光标的类型(手指)*/
float: left;
border: 1px solid #fff;
width: 10px;
height: 10px;
border-radius: 50%;
background: #333;
margin-right: 5px;
}
#buttons .on {
background: orangered;
}
.arrow {
cursor: pointer;
display: none; /*箭头隐藏*/
line-height: 39px;
text-align: center;
font-size: 36px;
font-weight: bold;
width: 40px; height: 40px;
position: absolute;
z-index: 2;
top: 180px;
background-color: RGBA(0,0,0,.3); /*透明度设置*/
color: #fff;
}
.arrow:hover {
background-color: RGBA(0,0,0,.7);
}
#container:hover .arrow {
display: block; /*箭头显示*/
}
#prev {
left: 20px;
}
#next {
right: 20px;
}


JS动画实现

箭头切换 -> 无限滚动 -> 按钮切换 -> 延迟切换 -> 自动播放

  1. 箭头切换

    • 整个页面加载window.onload,获取元素
    • 通过ID名获取页面中的元素(父容器、承载图片容器、圆点列表、箭头),赋值给一个变量
    • 添加一个时间绑定,点击箭头时实现图片的切换
    • 当点击右箭头时,改变left的值,向左移动,要减去一张图的宽度
    • 获取图片容器的值,list.style.left = 自身的值再减去一张图片的宽度
      注意要把等号后面字符串使用parseInt函数转换为数字才可以进行减法,减去的图片宽度要加px单位
    • 反方向同理,加上一张图片的宽度
    • 左右箭头的写法很相似,只是加减不一样,可以封装成一个函数,通过参数的正负值实现加减
  1. 无限滚动:弥补左右键切换的空白

    • 当前面的附属图比第一张大,最后一张附属图比最后一张小的时候,出现这两种情况时让它复位到真正的第一张或第五张图
    • 判断是否滚到了辅助图上,滚到了让它归位
    • 把常用的list.style.left,存到一个变量中,方便使用
    • 添加圆点的切换功能,创建一个变量来承载当前存储的第几张图片/显示第个圆点
    • 写一个函数,用来显示亮起小圆点的功能
      • 圆点是数组,所以创建的变量要减去1才能对应上要显示的圆点,让它亮起来添加class名
        <span index="1" class="on">
    • 再绑定事件中左箭头index要加一,右箭头要减一,调用圆点函数让它点击时显示,每次点击箭头的时候都要改变index的值,使它对应到正确的图片上,调用showButton亮起对应的圆点
    • 亮起自己的同时,让其他不亮,使用for循环,去掉所有的class,然后break退出循环,不再继续遍历元素节点
    • 箭头点击时,当圆点index大于5时,让它归位为1,小于1时,归位为5,不到5时加1
  1. 圆点按钮切换

    • 通过for循环遍历圆点,添加点击事件

    • 点击按钮时,取到index值,就可以知道当前点击的是第几个按钮,要显示第几张图片

    • 通过DOM2级方法getAttribute()获取到自定义(或自带)属性,为了计算再转换为数字var myIndex = parseInt(this.getAttribute('index'));

    • 通过新的值减去旧的值获取偏移量var offset = -600 * (myIndex - index);

    • 写一个判断,当这张图片是打开状态的,就什么都不做,用class=on来判断是否打开,return跳出,后面的代码不会再执行

      1
      2
      3
      4
      5
      6
      if (animated) {
      return;
      }
      if (this.className == 'on') {
      return;
      }
  1. 动画函数

    • 图片在一定时间内进行位移,要判断是否达到目标值,没有达到还要继续做位移
    • 声明一个变量用offset总共的偏移量除以次数(位移总时间time除以位移间隔时间inteval),求出每次移动多少var speed = offset / (time / inteval);
    • 判断speed小于0并且left值是否大于目标值newLeft或speed大于0并且left值小于目标值,这两种情况让它做位移speed > 0 && parseInt(list.style.left) < left) || (speed < 0 && parseInt(list.style.left) > left
    • 在判断中放入定时器setTimeout
      一个函数不停的在一定的条件之后调用自身这种做法叫做递归
  • 优化:声明一个变量,作为动画是否在运行的依据,开始状态为false表示没有运行var animated = false; //优化
  1. 自动播放

    • 鼠标移开时自动播放,鼠标移上去时停止,通过定时器setTimeoutclearTimeout来实现的
    • 设置定时器,让它隔几秒切换一次,相当于3秒钟调一次next.onclick(右箭头)事件
    • 自动切换需要写两个函数来控制自动切换,声明一个变量来存放定时器不给任何值
    • 鼠标移开时定时器执行,移上时清除定时器执行,要给整个容器加一个鼠标移入移开事件
    • 鼠标不做任何事情时让它自动播放,调用函数

代码如下

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
window.onload = function() {
var container = document.getElementById('container');
var list = document.getElementById('list');
var buttons = document.getElementById('buttons').getElementsByTagName('span');
var prev = document.getElementById('prev');
var next = document.getElementById('next');
var index = 1; //索引
var len = 5;
var animated = false; //优化
var interval = 3000; //时间间隔
var timer;
function showButton() {
for (var i = 0; i < buttons.length; i++) {
if (buttons[i].className == 'on') {
buttons[i].className = '';
break;
}
}
buttons[index - 1].className = 'on';
} //按钮切换
next.onclick = function() {
if (animated) {
return;
}
if (index == 5) {
index = 1;
} else {
index += 1;
}
animate(-600);
showButton();
}//右切换
prev.onclick = function() {
if (animated) {
return;
}
if (index == 1) {
index = 5;
} else {
index -= 1;
}
animate(600);
showButton();
}//左切换
function play() {
timer = setTimeout(function() {
next.onclick();
play();
}, interval);
}
function stop() {
clearTimeout(timer);
}
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = function() {
if (animated) {
return;
}
if (this.className == 'on') {
return;
}
var myIndex = parseInt(this.getAttribute('index'));
var offset = -600 * (myIndex - index);
animate(offset);
index = myIndex;
showButton();
}
}
function animate(offset) {
if (offset == 0) {
return;
}
animated = true;
var time = 300; //时间
var inteval = 10; //时间间隔
var speed = offset / (time / inteval); //速度
var left = parseInt(list.style.left) + offset; //改变值来实现滚动
var go = function() {
if ((speed > 0 && parseInt(list.style.left) < left) || (speed < 0 && parseInt(list.style.left) > left)) {
list.style.left = parseInt(list.style.left) + speed + 'px';
setTimeout(go, inteval);
} else {
list.style.left = left + 'px';
if (left > -200) {
list.style.left = -600 * len + 'px';
}
if (left < (-600 * len)) {
list.style.left = '-600px';
}
animated = false;
}
} //自动滚动
go();
}
container.onmouseover = stop();
container.onmouseout = play();
play();
}


总结

焦点轮播图的实现需要耐心分析原理,掌握焦点轮播图所需的技能点,从而通过代码实现。

先写出静态页面html+css,注意属性值的设置。再用js一步一步写出箭头切换、按钮切换的函数,学会设置和清除定时器、递归调用函数,实现自动滚动播放。

-------------本文结束感谢您的阅读-------------

本文标题:使用JavaScript实现焦点轮播图

文章作者:Awebone

发布时间:2017年12月29日 - 00:12

最后更新:2020年07月18日 - 16:07

原始链接:https://www.awebone.com/posts/7a7093e6/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。