使用JavaScript实现轮播图效果(JavaScript运动框架案例)

目录

前言

  轮播图组件是一种网站中常见的表现形式。常用于广告位,头条新闻等重要信息的展示而且将图片和信息结合起来,引人注意。轮播图最重要的自然是“轮播”,也就是要让页面中的DOM元素“动”起来。这就自然需要先简单提一下JavaScript的运动框架。


JavaScript运动框架简介

  JavaScript运动框架就是指利用js和DOM元素配合,利用js的相关函数以一定的频率操作改变DOM元素的位置,这样形成的连续效果就是DOM元素的任意运动。通过元素透明度,路径,速度,加速度,大小,颜色,字体等等方面的改变,可以形成很多很炫的效果,但是这里只展示一个最简单的例子,只为了说明问题,涉及到了元素加速度,速度,路径,大小。
  先展示一下基本的效果:

涉及到的几个要点是:
1.预先设计好想要的运动效果
2.合理使用setInterval()函数实现对元素的连续操作
3.使用clearInterval()及时清理不需要的计时器,防止多个计时器叠加导致运动混乱
4.“速度”的概念是通过setInterval()函数的执行间隔和指定的单位时间移动距离共同实现的
5.“加速度”的概念是通过将“一个固定的预定值”和“当前元素位置”的变化反映到速度上实现的

上述例子的完整代码如下:

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
<!DOCTYPE>
<html>
<head>
<meta charset="utf-8">
<title>move</title>
<script src="jquery-1.9.1.min.js"></script>
<!--简单设定元素样式-->
<style>
#div1 {
border: 1px solid darkgray;
border-radius: 5px;
width: 200px;
height: 50px;
position: absolute;
background-color: deepskyblue;
margin-top: 5px;
font-family: "Microsoft YaHei";
}
</style>

</head>
<body>
<div class="wrapper">
<button id="btn">点击演示</button>
<div id="div1">运动框架示例</div>
</div>
</body>
<script>
/*声明定时器*/
var timer = null;
$(function (){
$("#btn").click(function () {
clearInterval(timer);
moveFramework($("#div1"), 1000, 5);
})
})

var timer = null;
function moveFramework(element, moveTarget, speed) {
timer = setInterval(function () {
var left = $("#div1").offset().left;

/*速度大于零,向右运动*/
if(speed >= 0){
$("#div1").html("运动框架-->正向运动");
$("#div1").css("background-color", "deepskyblue");
/*达到运动边界后,改变初始值,递归调用下一次的控制函数*/
if(left >= moveTarget){
clearInterval(timer);
moveFramework(element, 0, -5);
} else {
/*加速度设置*/
speed = Math.ceil((moveTarget - left)/50);
element.css("left", left + speed + "px");
element.height(element.height() + 1);
}
} else {
/*速度小于零,向左运动*/
$("#div1").html("运动框架反向运动");
$("#div1").css("background-color", "yellow");
/*达到运动边界后,改变初始值,递归调用下一次的控制函数*/
if(left <= moveTarget){
clearInterval(timer);
moveFramework(element, 1000, 5);
} else {
/*加速度设置*/
speed = Math.floor((moveTarget - left)/50);
element.css("left", left + speed + "px");
element.height(element.height() - 1);
}
}
}, 10);
}
</script>

</html>


JavaScript轮播图组件实现过程

原理

  轮播图的实现充分结合了HTML+CSS+JavaScript。实现该效果并不是每点击一次“下一个”或者“上一个”就再去请求一张图片,而是渲染时一次性加载好所有内容,只不过为了实现这种动态轮播的效果,将其他图片做了隐藏,保证每次只展现一张。实现时,将一系列图片水平排列,通过父级元素宽度和overflow的设定,保证每次只看到一张,再通过JavaScript让元素动起来,定时修改包含一系列图片的容器的位置,实现轮播效果。更多原理的描述单靠文字会比较抽象,可以直接通过代码说明。

HTML基本结构

  文档结构最主要的及部分如下:
1.图片列表
2.图片下方背景层
3.图片左下角描述信息列表
4.图片右下角序号列表

完整代码如下:

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
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>js轮播图组件</title>
<script src="./js/jquery-1.9.1.min.js"></script>
<link rel="stylesheet" type="text/css" href="./css/carousel.css">
</head>
<body>
<!-- 最外层包裹 -->
<div id="wrapper">
<!-- 轮播图组件 -->
<div id="banner">
<!-- 图片列表 -->
<ul class="imgList">
<li><a href="#"><img src="./img/1.jpg" alt="picture 1 图片描述"></a></li>
<li><a href="#"><img src="./img/2.jpg" alt="picture 2 图片描述"></a></li>
<li><a href="#"><img src="./img/3.jpg" alt="picture 3 图片描述"></a></li>
<li><a href="#"><img src="./img/4.jpg" alt="picture 4 图片描述"></a></li>
<li><a href="#"><img src="./img/5.jpg" alt="picture 5 图片描述"></a></li>
</ul>
<!-- 左右选择箭头 -->
<img src="./img/left_arrow.png" width="21px" height="33px" id="prev">
<img src="./img/right_arrow.png" width="21px" height="33px" id="next">
<!-- 图片底部背景层-->
<div class="bg"></div>
<!-- 图片左下方信息列表 -->
<ul class="infoList">
<li class="infoOn">picture 1 图片描述</li>
<li>picture 2 图片描述</li>
<li>picture 3 图片描述</li>
<li>picture 4 图片描述</li>
<li>picture 5 图片描述</li>
</ul>
<!-- 图片右下方序号列表 -->
<ul class="indexList">
<li class="indexOn">1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</div>
</div>
<script src="./js/carousel.js"></script>
</body>
</html>

CSS设计

  在轮播图的实现中,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
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
/*整体清除margin padding*/
body,div,ul,li,a,img {
margin: 0;
padding: 0;
}

/*设置列表及元素无修饰样式-指无序列表前的小方点或小圆点*/
ul,li {
list-style: none;
}

/*设置轮播图片大小*/
.imgList img {
width: 800px;
height: 400px;
}

/*设置超链接无修饰样式-指下划线等*/
a {
text-decoration: none;
}

/*设置轮播图最外层包裹元素样式,为相对定位(这样子元素方便以绝对定位的方式相对wrapper进行定位),margin的auto可以保证元素自适应居中*/
#wrapper {
position: relative;
margin: 30px auto;
width: 800px;
height: 400px;
}

/*设置轮播图组件的容器样式,重点在于overflow: hidden;正是它保证了多余图片隐藏,只显示一张*/
#banner {
position:relative;
width: 800px;
height: 400px;
overflow: hidden;
}

/*设置图片列表的样式,每张图片宽800px,共5张图片,故总宽度800*5=4000px。*/
.imgList {
position:relative;
width:4000px;
height:400px;
z-index: 10;
overflow: hidden;
}

/*设置图片列表中每个元素-即每张图片的样式,向左浮动保证图片显示在一行*/
.imgList li {
float:left;
}

/*设置“前一张”、“后一张”按钮的样式,绝对定位,相对于最近的一个relative父级元素*/
#prev,
#next {
position: absolute;
top:160px;
z-index: 20;
cursor: pointer;
opacity: 0.8;
}

/*单独设置一下“前一张”按钮距左边的距离*/
#prev {
left: 10px;
}

/*单独设置一下“后一张”按钮距右边的距离*/
#next {
right: 10px;
}

/*设置“前一张”、“后一张”按钮的伪类hover效果*/
#prev:hover,
#next:hover {
opacity: 0.9;
}

/*设置图片下方背景区样式,绝对定位,相对于最近的一个relative父级元素;一定要设置透明度,更加美观*/
.bg {
position: absolute;
bottom: 0;
width: 100%;
height: 50px;
z-index:20;
opacity: 0.4;
font-family: "Microsoft YaHei";
background: whitesmoke;
}

/*设置图片左下方文字描述列表的样式*/
.infoList {
position: absolute;
left: 10px;
bottom: 15px;
z-index: 30;
}

/*设置文字描述中每一个元素的样式,注意一定要设置display: none;,不然所有图片的文字描述会一次性全显示出来。后续通过js让其逐一显示*/
.infoList li {
display: none;
font-family: "Microsoft YaHei";
}

/*设置当前正展示的图片的文字描述样式*/
.infoList .infoOn {
display: inline;
color: white;
}

/*设置图片右下方序号列表的样式*/
.indexList {
position: absolute;
right: 10px;
bottom: 10px;
z-index: 30;
}

/*设置序号列表中每一个元素的样式,向左浮动保证显示在一行*/
.indexList li {
float: left;
margin-right: 5px;
padding: 2px 4px;
border: 1px solid white;
border-radius: 3px;
background: grey;
cursor: pointer;
font-family: "Microsoft YaHei";
}

/*设置序号列表中每一个元素的hover样式*/
.indexList li:hover {
background:deepskyblue;
}

/*设置当前正展示的图片的序号样式*/
.indexList .indexOn {
background: greenyellow;
font-weight: bold;
color: orangered;
}

JavaScript控制逻辑

  JavaScript的控制逻辑本质上和前面提到的运动框架是一样的,完整代码如下:

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
/**
* Created by gaochang on 2016/6/3.
*/


//当前index
var curIndex = 0;

//图片总数
var imgLen = $(".imgList li").length;

// 定时器 每两秒切换一次
var autoChange = setInterval(function(){
if(curIndex < imgLen-1){
curIndex ++;
}else{
curIndex = 0;
}
//调用变换处理函数
changeTo(curIndex);
},2000);

//左箭头滑入滑出事件处理
$("#prev").hover(function(){
//滑入清除定时器,接着再去等待点击事件
clearInterval(autoChange);
},function(){
//滑出则重置定时器,接着继续自动切换
autoChangeAgain();
});

//左箭头点击处理
$("#prev").click(function(){
//根据curIndex进行上一个图片处理
curIndex = (curIndex > 0) ? (--curIndex) : (imgLen - 1);
changeTo(curIndex);
});

//右箭头滑入滑出事件处理
$("#next").hover(function(){
//滑入清除定时器,接着再去等待点击事件
clearInterval(autoChange);
},function(){
//滑出则重置定时器,接着继续自动切换
autoChangeAgain();
});

//右箭头点击处理
$("#next").click(function(){
curIndex = (curIndex < imgLen - 1) ? (++curIndex) : 0;
changeTo(curIndex);
});

//对右下角按钮index进行事件绑定处理等
$(".indexList").find("li").each(function(item){
$(this).click(function(){
clearInterval(autoChange);
changeTo(item);
curIndex = item;
autoChangeAgain();
})
});

//清除定时器时候的重置定时器--封装
function autoChangeAgain(){
autoChange = setInterval(function(){
if(curIndex < imgLen-1){
curIndex ++;
}else{
curIndex = 0;
}
//调用变换处理函数
changeTo(curIndex);
},2000);
}

function changeTo(num){
var goLeft = num * 800;
$(".imgList").animate({
left: "-" + goLeft + "px",
},500);

$(".infoList").find("li").removeClass("infoOn").eq(num).addClass("infoOn");
$(".indexList").find("li").removeClass("indexOn").eq(num).addClass("indexOn");
}

效果展示

  轮播图的效果如下:

可以扩展的地方

  上述过程已经实现了基本的轮播图,但是还可以对效果进行丰富,可以考虑的方面比如:
1.加上立体效果,如正在展示的图片加上倒影效果,且可以看到全部图片,只不过其他图片(除了正在展示的图片)都缩小/加毛玻璃效果等;
2.在轮播图组件最下方增加全部图片缩略图预览,使得不仅可以点击序号,还可以直接点击某个缩略图到达具体对应的大图;