jQuery实现轮播(一)

实现一个轮播效果。

一、结构、表现、行为的分离

这个很重要,见过后台小哥哥写的前台代码(仅限于html+css),简直惨不忍睹,各种内联样式,….此处省略一万字吐槽内容。
言归正传,结构、表现、行为分离主要是指将html代码与样式和js文件最大限度解耦,主要表现在:

  • 标签内尽量不写样式,样式全部通过样式表加载
  • 样式的改变通过改变节点类名进行修改
  • 标签内尽量不要写如:onclick、onmouseenter等事件
  • js最好是通过文件引入,最好不放在页面中

差不多就这些吧。

二、开始轮播

1、图片与页面优化

在图片很多的页面中,<img>标签最好将图片的宽高卸载标签如,

1
<img sr="xxx.png" width=100 height=100>

这么做的原因是,如果图片未设置宽高且图片尚未加载出来,后面的元素就会占用前面图片的位置,当图片加载完成后,紧跟在图片后面的元素就要让出占用当前图片的位置,而这个元素移动位置的过程是比较耗CPU的,这个过程就叫做CSS重排

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
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
//===========html===========
<!DOCTYPE html>
<html>
<head>
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div class="window">
<div class="images" id="images">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
</div>
<div class="btn">
<button id="loop1">轮播1</button>
<button id="loop2">轮播2</button>
<button id="loop3">轮播3</button>
</div>

</body>
</html>
//===========css===========
.images>div{
width:200px;
height:200px;
background:#fcc;
text-align:center;
line-height:200px;
display:inline-block;
vertical-align:top;
font-size:14px;
}
.images{
width:600px;
font-size:0px;
transition:all 0.3s ease-in-out;
}
.btn{
margin-top:20px;
}
.window{
width:200px;
height:200px;
overflow:hidden;
}
//========js============
loop1.onclick = function(){
$('#images').css({
transform:'translateX(0)'
})
}
loop2.onclick = function(){
$('#images').css({
transform:'translateX(-200px)'
})
}
loop3.onclick = function(){
$('#images').css({
transform:'translateX(-400px)'
})
}

3、支持多张轮播

以上代码可看出只有三个div(图片)参与轮播,此时我们可以将按钮跟div一一对应,如果div(图片)个数为止,那么一一对应绑定事件则无效,解决方案为:

1
2
3
4
5
6
7
8
9
10
11
//========仅仅修改JS代码========
let allBtns = $('.btn > button');
for(let i = 0;i<allBtns.length;i++){
$(allBtns[i]).on('click',function(x){
let index = $(x.currentTarget).index();
let move = index * -200;
$('.images').css({
transform:'translateX('+ move +'px)'
})
})
}

4、自动播放

根据以上js代码修改可完成自动播放:

1
2
3
4
5
let n = 0;
let t = setInterval(function(){
n++;
allBtns.eq(n%3).trigger('click');
},2000)

5、鼠标悬停暂停播放,离开继续播放

1
2
3
4
5
6
7
8
9
$('.window').on('mouseenter',function(){
clearInterval(t);
})
$('.window').on('mouseleave',function(){
t = setInterval(function(){
n++;
allBtns.eq(n%size).trigger('click').addClass('red').siblings().removeClass('red');
},2000)
})

6、代码优化

将上述JS代码进行合并:

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
let allBtns = $('.btn > button');
for(let i = 0;i<allBtns.length;i++){
$(allBtns[i]).on('click',function(x){
let index = $(x.currentTarget).index();
let move = index * -200;
$('.images').css({
transform:'translateX('+ move +'px)'
})
})
}

let n = 0;
let size = $('.images > div').length;
let t = autoPlay();

$('.window').on('mouseenter',function(){
clearInterval(t);
})
$('.window').on('mouseleave',function(){
t = autoPlay();
})

function setStatus($btn){
$btn.addClass('red').siblings().removeClass('red');
}
function playSwiper(obj){
obj.eq(n%size).trigger('click');
setStatus(obj.eq(n%size));
}
function autoPlay(){
return setInterval(function(){
n++;
playSwiper(allBtns);
},2000)
}

三、无缝轮播

1、关于动画完成后的回调

在所有具有动画效果的dom节点都可绑定此事件:

1
$(DOM).one('transitionend',function(){})

2、无缝轮播效果

1)基本代码
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
//===页面结构同二中的结构一致===
//===========less=========
*{
padding: 0px;
margin: 0px;
}
.images > img{
background: #fcc;
width: 100%;
position: absolute;
left: 0%;
top: 0%;
transition: all 0.3s ease-in-out;
transform: translateX(100%);
z-index: 1;
&:nth-child(1){
transform: translateX(0);
}
&.current{
transform: translateX(0);
z-index: 4;
}
&.leave{
transform: translateX(-100%);
}
&.enter{
transform: translateX(100%);
}
}
.images{
display: flex;
position: relative;
height: 100%;
width: 100%;
}
.window{
height: 200px;
width: 200px;
overflow: hidden;
margin: 20px auto;
}
.red{
color: red;
}
.btns{
text-align: center;
}
//===========JS===========
//初始化位置
init();
let n = 1;
let size = $('.images img').length;
let imgs = $('.images img');
let t = setInterval(function(){
let idx = n % size;
let target = $(imgs[idx]).attr('class','current');
if(idx === 0){
$(imgs[size - 1]).attr('class','leave').one('transitionend',(e)=>{
$(e.currentTarget).attr('class','enter')
});
//target.next().attr('class','enter');
}else if(idx === (size - 1)){
//$(imgs[0]).attr('class','enter');
target.prev().attr('class','leave').one('transitionend',(e)=>{
$(e.currentTarget).attr('class','enter')
});
}else{
//target.next().attr('class','enter');
target.prev().attr('class','leave').one('transitionend',(e)=>{
$(e.currentTarget).attr('class','enter')
});
}
n++;
},2000);

//初始化位置
function init(){
let target = $('.images img');
for(let i = 0;i<target.length;i++){
if(i === 0){
$(target[i]).addClass('current');
}else{
$(target[i]).addClass('enter');
}
}
}
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//只优化JS代码
//初始化位置
init();
let n = 1;
let size = $('.images img').length;
let imgs = $('.images img');
let t = setInterval(function(){
$('#html').html(setVal(n+1));
makeLeave(getImage(n)).one('transitionend',(e)=>{
makeEnter($(e.currentTarget))
});
makeCurrent(getImage(n+1));
n++;
},2000);

//处理n的值
function setVal(n){
let size = $('.images img').length;
if(n >= size){
n = n % size === 0 ? size : (n % size);
}
return n;
}

//初始化位置
function init(){
let target = $('.images img');
for(let i = 0;i<target.length;i++){
if(i === 0){
$(target[i]).addClass('current');
}else{
$(target[i]).addClass('enter');
}
}
}

function makeLeave($node){
return $node.removeClass('enter current').addClass('leave');
}
function makeEnter($node){
return $node.removeClass('current leave').addClass('enter');
}
function makeCurrent($node){
return $node.removeClass('enter leave').addClass('current');
}
function getImage(n){
return $(`.images img:nth-child(${setVal(n)})`);
}

以上代码效果可通过Github查看:
初始轮播
无缝轮播一
无缝轮播二

转载请注明出处。