本文转载于:猿2048网站⇨HTML5手机开发学习:实现滚动和惯性缓动效果
滚动
以下是三种实现方式:
1) 利用原生的css属性 overflow: scroll
<div id="parent" style="overflow:scroll;>
<div id='content'>内容区域</div>
</div>
Notice:在android 有bug, 滚动完后会回退到最顶端的内容区域,解决办法是使用后两种方式实现
2)js 编程实现
思路:对比手指在屏幕上移动前后位置变化改变内容元素content的位置
第一步:设置parent的 overflow为hidden, 设置content的position为relative, top为0;
第二步:监听touch事件
1
2
3
4
5
6
7
8
9
10
|
var
parent = document.getElementById(
'parent'
);
parent.addEventListener(
'touchstart'
,
function
(e) {
// do touchstart
});
parent.addEventListener(
'touchmove'
,
function
(e) {
// do touchmove
});
parent.addEventListener(
'touchend'
,
function
(e) {
// do touchend
});
|
第三步:实现滚动代码
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
|
/**
* 这里只实现垂直滚动
*/
var
parent = document.getElementById(
'parent'
);
var
content = document.getElementById(
'content'
)
var
startY = 0;
// 初始位置
var
lastY = 0;
// 上一次位置
parent.addEventListener(
'touchstart'
,
function
(e) {
lastY = startY = e.touches[0].pageY;
});
parent.addEventListener(
'touchmove'
,
function
(e) {
var
nowY = e.touches[0].pageY;
var
moveY = nowY - lastY;
var
contentTop = content.style.top.replace(
'px'
,
''
);
// 设置top值移动content
content.style.top = (parseInt(contentTop) + moveY) +
'px'
;
lastY = nowY;
});
parent.addEventListener(
'touchend'
,
function
(e) {
// do touchend
var
nowY = e.touches[0].pageY;
var
moveY = nowY - lastY;
var
contentTop = content.style.top.replace(
'px'
,
''
);
// 设置top值移动content
content.style.top = (parseInt(contentTop) + moveY) +
'px'
;
lastY = nowY;
});
|
第四步:优化
上边代码在手机上运行效果相对PC上要卡很多
) 使用iScroll4框架
var scroll = new iScroll('parent', {
hScrollbar: false,
vScrollbar: true,
checkDOMChanges : true
});
框架官网: http://cubiq.org/iscroll-4
惯性缓动
思路:取手指最后一段时间在屏幕上划动的平均速度v,让v按一个递减函数变化,直到不能移动或v<=0
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
|
/**
* 这里只实现垂直滚动
*/
var
parent = document.getElementById(
'parent'
);
var
content = document.getElementById(
'content'
)
var
startY = 0;
// 初始位置
var
lastY = 0;
// 上一次位置
/**
* 用于缓动的变量
*/
var
lastMoveTime = 0;
var
lastMoveStart = 0;
var
stopInertiaMove =
false
;
// 是否停止缓动
parent.addEventListener(
'touchstart'
,
function
(e) {
lastY = startY = e.touches[0].pageY;
/**
* 缓动代码
*/
lastMoveStart = lastY;
lastMoveTime = e.timeStamp || Date.now();
stopInertiaMove =
true
;
});
parent.addEventListener(
'touchmove'
,
function
(e) {
var
nowY = e.touches[0].pageY;
var
moveY = nowY - lastY;
var
contentTop = content.style.top.replace(
'px'
,
''
);
// 设置top值移动content
content.style.top = (parseInt(contentTop) + moveY) +
'px'
;
lastY = nowY;
/**
* 缓动代码
*/
var
nowTime = e.timeStamp || Date.now();
stopInertiaMove =
true
;
if
(nowTime - lastMoveTime > 300) {
lastMoveTime = nowTime;
lastMoveStart = nowY;
}
});
parent.addEventListener(
'touchend'
,
function
(e) {
// do touchend
var
nowY = e.touches[0].pageY;
var
moveY = nowY - lastY;
var
contentTop = content.style.top.replace(
'px'
,
''
);
var
contentY = (parseInt(contentTop) + moveY);
// 设置top值移动content
content.style.top = contentY +
'px'
;
lastY = nowY;
/**
* 缓动代码
*/
var
nowTime = e.timeStamp || Date.now();
var
v = (nowY - lastMoveStart) / (nowTime - lastMoveTime);
//最后一段时间手指划动速度
stopInertiaMove =
false
;
(
function
(v, startTime, contentY) {
var
dir = v > 0 ? -1 : 1;
//加速度方向
var
deceleration = dir*0.0006;
var
duration = v / deceleration;
// 速度消减至0所需时间
var
dist = v * duration / 2;
//最终移动多少
function
inertiaMove() {
if
(stopInertiaMove)
return
;
var
nowTime = e.timeStamp || Date.now();
var
t = nowTime-startTime;
var
nowV = v + t*deceleration;
// 速度方向变化表示速度达到0了
if
(dir*nowV < 0) {
return
;
}
var
moveY = (v + nowV)/2 * t;
content.style.top = (contentY + moveY) +
"px"
;
setTimeout(inertiaMove, 10);
}
inertiaMove();
})(v, nowTime, contentY);
});
|
更多专业前端知识,请上 【猿2048】www.mk2048.com