轮播图总结以及组件化思考

缘起

近日不断的入坑vue, 然后看到了相应的mint-ui 中的轮播图组件, 进而想复习一下轮播图这个经典js对象. 讲真, 原先用原生js写过轮播图(貌似每个前端攻城狮都应该用原生js写过轮播图吧?)但是我们知道轮播图是相对而言有一些复杂的函数体. 涉及的逻辑控制较多(高手勿喷, 只针对初学者). 所以想彻底理一理, 朝着组件化思想去重构它. 遂有了本文.

分析

1. 经典的轮播图

1556458391201

2. 功能点

  1. 不做任何操作的话, 轮播图会自动播放(播放属于平滑过渡). 播放的时候, 上面的箭头是不会出现的. 下方的小圆点的样式不断变化
  2. 鼠标悬浮在轮播图上方, 出现箭头,并且自动轮播停止, 鼠标悬浮在箭头上方, 箭头的背景色加深,点击箭头,轮播图翻页
  3. 点击下方的小圆点, 轮播图翻页, 并且小圆点的样式发生改变.

3. 组件拆分

首先, 整个功能拆分为html+css+js(这符合vue组件的思想,vue中叫template+style+script)

3.1 html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div id="container">
<div id="list" style="left: -600px;">
<!--5.jpg 是最后一张图片-->
<img src="img/5.jpg" alt="5"/>
<!--1.jpg是第一张图片-->
<img src="img/1.jpg" alt="1"/>
<img src="img/2.jpg" alt="2"/>
<img src="img/3.jpg" alt="3"/>
<img src="img/4.jpg" alt="4"/>
<img src="img/5.jpg" alt="5"/>
<!--衔接上-->
<img src="img/1.jpg" alt="1"/>
</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>

简而言之, 就是放在一个container中, container中分成三部分

  1. 图片列表
  2. 按钮
  3. 箭头
3.2 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
<style type="text/css">

/*最外围的div*/
#container {
margin: 0 auto;
padding: 0;
text-decoration: none; /*去除内边距,没有链接下划线*/
width: 600px;
height: 400px;
overflow: hidden; /*截掉多余的, 只看到第一张图片*/
position: relative; /*相对定位*/
}

/*包含所有图片的<div>*/
#list {
width: 4200px; /*7张图片的宽*/
height: 400px;
position: absolute; /*绝对定位*/
}

/*所有的图片<img>*/
#list img {
float: left; /*浮在左侧 让所有的图片水平排列*/
width: 600px;
height: auto;
}

/*包含所有圆点按钮的<div>*/
#buttons {
position: absolute;
height: 10px;
width: 100px;
z-index: 2; /*压在图片上方*/
bottom: 20px;
left: 250px;
}

/*所有的圆点<span>*/
#buttons span {
cursor: pointer;
float: left;
border: 1px solid #fff;
width: 10px;
height: 10px;
border-radius: 50%;
background: #333;
margin-right: 5px;
}

/*第一个<span>*/
#buttons .on {
background: orangered;
}

/*切换图标<a>*/
.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, 0.3);
color: #fff;
}

/*鼠标移到切换图标上时 背景色突然加深(0.3 变成 0.7)*/
.arrow:hover {
background-color: RGBA(0, 0, 0, 0.7);
}

/*鼠标移到整个div区域时*/
#container:hover .arrow {
display: block; /*显示*/
}

/*上一个切换图标的左外边距*/
#prev {
left: 20px;
}

/*下一个切换图标的右外边距*/
#next {
right: 20px;
}
</style>

简而言之,就是

  1. container相对定位, 里面的三部分都是绝对定位.
  2. container的尺寸就只能容下一张图片, 而图片列表的长度就是所有图片横向浮动排列之后的总宽度. container要overflow:hidden
3.3 js

最关键的就是翻页函数了. 翻页函数有3处会被调用

  1. 自动翻页
  2. 点击箭头
  3. 点击小圆点

其中, 1、2和 3是不同的. 因为3的入参是我要展示哪张图片. 而1、2要入参的是方向参数, 即到底是向哪个方向翻页. 所以翻页函数的入参有2种. 一种是boolean值一种是整型. 而且不难想象是翻页函数要触发一个计时器,谈到计时器, 整个轮播图有2个计时器,另一个就是自动翻页这个计时器. 而且在翻页动画的过程中,该动画是被设置为不可打断的. 即存在一个标识防止动画被打断.

翻页函数中最为tricky的地方在于轮播到最后再进一步的展示. 它其实是这样的

假设要展示的图片是

1 2 3 4 5

则实际图片的排列是(1’和5’ 分别是1 和5的复制品. 使用dom复制很容易做到这一点)

5’ 1 2 3 4 5 1’

轮播的顺序是从1~5,然后要展示1的时候,其实展示的是1’. 展示完1’之后立马将 imgList的left变成 1的left,则下一步就变成了2. 这样就衔接上了. 注意,有的童鞋可能会问,为什么不展示完5之后立马将left变成1的left呢? 这样就不需要 1’了呀~但是这样的话, 1将不会被展示而直接展示的是2. 就不连贯了. 其实这个道理对于5’的缘起是一样的. 如果1左移一张图, 则我要展示的应该是5, 但其实我展示的是5’, 展示完5’ 立马将left变成 5的left值, 则下一次展示的就是4,这样就不突兀了. 这就是轮播图的核心思想.

具体代码不在这里贴了. 在DEMO【1】中参看. 这是一款即经典又简明的轮播图组件

4. 组件化

在大前端的今天,组件化、模块化一直是必然的趋势. 所以我们写任何一段代码,都要考虑其封装性. 既然是封装, 我们首当其冲需要考虑的是需要对外暴露的东西是什么.

  1. 轮播图片的张数.
  2. 每张图片的宽高. imgWidth 、imgHeight
  3. 每次翻页耗时 timecost
  4. 自动翻页的时间间隔 pageInterval

而我可以规定用户使用的html结构仅仅为(非常的轻量级和低污染性, 代码的侵入性很低) 注意, imgWidth、imgHeight、timecost、pageInterval 这些都有默认值 其中 swipercontainer这个id是不能改变的

1
2
3
4
5
6
7
<div id="container" imgWidth="600" imgHeight="400" timecost="400" pageInterval="1000" >
<img src="img/1.jpg" />
<img src="img/2.jpg" />
<img src="img/3.jpg" />
<img src="img/4.jpg" />
<img src="img/5.jpg" />
</div>

然后引入我的轮播图组件js

1
2
<link rel="stylesheet" href="swiper.css"/>
<script type="text/javascript" src="swiper.js">

即可展示经典轮播图效果.

DEMO

【1】https://github.com/yfsyfs/front/tree/master/%E5%8E%9F%E7%94%9Fjs%E5%86%99%E7%9A%84%E8%BD%AE%E6%92%AD%E5%9B%BE%E7%BB%84%E4%BB%B6