Null's Blog

移动端slider的实现

slider插件,我想很多人都用过,也有不少人写过,但别人写的,多少都不能满足眼前的实际需要。
现在的需求是:移动端3D展示效果,这里当然是伪3D,使用多张图片,通过切换达成类似3D的效果,因为是移动端,所以决定使用CSS3的的transform,一般的手机浏览对CSS3的transform会提供更底层的硬件加速。功能简单,力求轻巧高效,就自己实现了。

首先规定html dom结构:

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
<!--boss sb 要31张这么多吗?-->
<div class="slidermain">
<ul>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
<li><div style="background-image:url(http://statics.nullcn.com/blog/images/c0000.jpg)"></div></li>
</ul>
</div>

slider代码核心部分

很简单,只是使用$修改ul的偏移量 这很好理解:

1
2
3
4
5
6
7
8
9
10
11
12
function sliderTo(element,index){
var sliderCount = element.find('li').length;
element.find('ul').css({
transform: 'translateX(-' + 100 / sliderCount * (index-1) + '%)',
'-webkit-transform': 'translateX(-' + 100 / sliderCount * (index-1) + '%)'
});
defaults.touchbacks(index);
if(defaults.scurpage != index){
defaults.scurpage = index;
touchMoveStartCoordinate = touchCrossCoordinate;
}
}

加入 swipe 滑动功能 自动调整dom结构 自动旋转一周的功能等:

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
;(function($){
function sliderTo(element,index){
var sliderCount = element.find('li').length;
element.find('ul').css({
transform: 'translateX(-' + 100 / sliderCount * (index-1) + '%)',
'-webkit-transform': 'translateX(-' + 100 / sliderCount * (index-1) + '%)'
});
defaults.touchbacks(index);
if(defaults.scurpage != index){
defaults.scurpage = index;
touchMoveStartCoordinate = touchCrossCoordinate;
}
}
var defaults={
scurpage: 0,
height:240,
callbacks: function() {},
touchbacks: function() {}
}
var flag;
var touchMoveStartCoordinate = {}; //touch 坐标
var touchDistanceCoordinate = {}; //touch start 到 touch end 距离
var touchCrossCoordinate = {}; //touch 经过 的坐标
$.extend($.fn,{
tinyRotaClick: function(opts) {
var element = $(this);
defaults = $.extend(defaults, opts);
var s = defaults.scurpage + 1;
/*if(s>=9){
s=1;
}*/
sliderTo(element, s);
},
tinySlider : function(opts){
defaults = $.extend(defaults,opts);
defaults.scurpage = defaults.scurpage + 1;
var element = $(this);
element.css({
position: 'relative',
width: '100%',
height: defaults.height+'px',
overflow: 'hidden'
});
var sliderLength = element.find('li').length;
element.find('ul').css({
position: 'absolute',
transform: 'translateX(0%)',
'-webkit-transform': 'translateX(0%)',
padding: '0px',
margin: '0px',
height: '100%',
width: sliderLength + '00%'
});
element.find('li').css({
width: '100%',
height: '100%',
padding: '0px',
margin: '0px',
'list-style': 'none',
'float': 'left',
width: 100/sliderLength+'%'
});
sliderTo(element, defaults.scurpage);
defaults.callbacks();
element[0].addEventListener('touchstart', function(e) {
function onTouchMove(e) {
var touch = e.touches[0];
touchCrossCoordinate = {
x: touch.pageX,
y: touch.pageY
};
touchDistanceCoordinate = {
x: touch.pageX - touchMoveStartCoordinate.x,
y: touch.pageY - touchMoveStartCoordinate.y
};
if(Math.abs(touchDistanceCoordinate.x) < Math.abs(touchDistanceCoordinate.y)){
flag = true;
}
if(flag){
e.preventDefault();
}
if(touchDistanceCoordinate.x > 20){
if(defaults.scurpage===1){
sliderTo(element,sliderLength);
}else{
sliderTo(element,defaults.scurpage-1);
}
}else if(touchDistanceCoordinate.x < -20){
if(defaults.scurpage===sliderLength){
sliderTo(element,1);
}else{
sliderTo(element,defaults.scurpage+1);
}
}
};
function onTouchEnd() {
element[0].removeEventListener("touchmove", onTouchMove, false),
element[0].removeEventListener("touchend", onTouchEnd, false)
}
var touch = e.touches[0];
touchMoveStartCoordinate = {
x: touch.pageX,
y: touch.pageY,
time: +new Date
},
//flag = void 0,
touchDistanceCoordinate = {};
element[0].addEventListener("touchmove", onTouchMove, false);
element[0].addEventListener("touchend", onTouchEnd, false);
},false);
}
});
})(Zepto);

如何使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//初始化
$('.slidermain').tinySlider({
scurpage: 0,
height:300,
touchbacks: function(index) {
}
});
var sliderLength = 30;
function SliderRota(){
setTimeout(function () {
$('.slidermain').tinyRotaClick({});
sliderLength = sliderLength - 1;
if(sliderLength>1){
SliderRota();
}
}, 50);
}

** demo:tinySliderDemo tinySliderDemo

tinySlider已开源:tinySlider