代码改变世界

[iPad]手势及分页

2011-09-12 17:09  dreamliu  阅读(949)  评论(0编辑  收藏  举报

距离写上一篇文章已经好久了,有了用js调用webservice获取数据之后现在面对的就是对数据的呈现,对于大量的数据分页是个好的选择,在网页上我们通常都是通过点上一页下一页链接来实现分页显示,在ipad上虽然也可以这么实现,但是显得好生另类,也失去了好的用户体验。滑动翻页,没错啦,下面就来说下实现滑动翻页的事情。

iOS上的Safari也支持click 和mouseover等传统的交互事件,只是不推荐在iOS的浏览器应用上使用click和mouseover,因为这两个事件是为了支持鼠标点击而设计出来的。Click事件在iOS上会有半秒左右的延迟,原因是iOS要highlight接收到click的element。而mouseover/out等事件则会被手指的点击触发。所以,在iOS上,应当抛弃传统的交互事件模型而接受一个新的事件模型。Touch事件和更高级的Gesture事件,能让你的网页交互起来像native应用一样。

需要了解的Touch事件:

touchstart:  // 手指放到屏幕上的时候触发

touchmove:  // 手指在屏幕上移动的时候触发

touchend:  // 手指从屏幕上拿起的时候触发

touchcancel:  // 系统取消touch事件的时候触发

现在就可以通过处理Touch事件来跟踪用户的每一根手指的位置,比较其初始的位置来实现相应的翻页动作。

先几句通用的代码来实现注册事件和网页层控制操作: 

View Code
  1 var Commom = {
2
3 $get: function (objName) { if (document.getElementById) { return eval('document.getElementById("' + objName + '")') } else { return eval('document.all.' + objName) } },
4 //Event
5 addEvent: function (obj, eventType, func) { if (obj.attachEvent) { obj.attachEvent("on" + eventType, func); } else { obj.addEventListener(eventType, func, false) } },
6 delEvent: function (obj, eventType, func) { if (obj.detachEvent) { obj.detachEvent("on" + eventType, func) } else { obj.removeEventListener(eventType, func, false) }
7
8 },
9
10 //Style
11
12 readStyle: function (i, I) { if (i.style[I]) { return i.style[I] } else if (i.currentStyle) { return i.currentStyle[I] } else if (document.defaultView && document.defaultView.getComputedStyle) { var l = document.defaultView.getComputedStyle(i, null); return l.getPropertyValue(I) } else { return null } },
13
14 absPosition: function (obj, parentObj) { //位置
15
16 var left = obj.offsetLeft;
17
18 var top = obj.offsetTop;
19
20 var tempObj = obj.offsetParent;
21
22 var sss = "";
23
24 try {
25
26 while (tempObj.id != document.body && tempObj.id != document.documentElement && tempObj != parentObj && tempObj != null) {
27
28 sss += tempObj.tagName + " , ";
29
30 tempObj = tempObj.offsetParent;
31
32 left += tempObj.offsetLeft;
33
34 top += tempObj.offsetTop;
35
36 };
37
38 } catch (e) { };
39
40 return { left: left, top: top };
41
42 },
43
44 style: {
45
46 setOpacity: function (obj, opacity) {
47
48 if (typeof (obj.style.opacity) != 'undefined') {
49
50 obj.style.opacity = opacity;
51
52 } else {
53
54 obj.style.filter = 'Alpha(Opacity=' + (opacity * 100) + ')';
55
56 };
57
58 }
59
60 },
61
62 extend: {
63
64 show: function (obj, timeLimit) {
65
66 if (Commom.readStyle(obj, 'display') === 'none') {
67
68 obj.style.display = 'block';
69
70 };
71
72 Commom.style.setOpacity(obj, 0);
73
74 if (!timeLimit) {
75
76 timeLimit = 200;
77
78 };
79
80 var opacity = 0, step = timeLimit / 20;
81
82 clearTimeout(obj._extend_show_timeOut);
83
84 obj._extend_show_timeOut = setTimeout(function () {
85
86 if (opacity >= 1) {
87
88 return;
89
90 };
91
92 opacity += 1 / step;
93
94 Commom.style.setOpacity(obj, opacity);
95
96 obj._extend_show_timeOut = setTimeout(arguments.callee, 20);
97
98 }, 20);
99
100 },
101
102 hide: function (obj, timeLimit) {
103
104 if (!timeLimit) {
105
106 timeLimit = 200;
107
108 };
109
110 Commom.style.setOpacity(obj, 1);
111
112 var opacity = 1, step = timeLimit / 20;
113
114 clearTimeout(obj._extend_show_timeOut);
115
116 obj._extend_show_timeOut = setTimeout(function () {
117
118 if (opacity <= 0) {
119
120 obj.style.display = 'none';
121
122 Commom.style.setOpacity(obj, 1);
123
124 return;
125
126 };
127
128 opacity -= 1 / step;
129
130 Commom.style.setOpacity(obj, opacity);
131
132 obj._extend_show_timeOut = setTimeout(arguments.callee, 20);
133
134 }, 20);
135
136 },
137
138 actPX: function (obj, key, start, end, speed, endFn, u) {
139
140 if (typeof (u) == 'undefined') { u = 'px' };
141
142 clearTimeout(obj['_extend_actPX' + key.replace(/\-\.\=/, '_') + '_timeOut']);
143
144 if (start > end) {
145
146 speed = -Math.abs(speed);
147
148 } else {
149
150 speed = Math.abs(speed);
151
152 };
153
154 var now = start;
155
156 var length = end - start;
157
158 obj['_extend_actPX' + key.replace(/\-\.\=/, '_') + '_timeOut'] = setTimeout(function () {
159
160 now += speed;
161
162 var space = end - now;
163
164 if (start < end) {
165
166 if (space < length / 3) {
167
168 speed = Math.ceil(space / 3);
169
170 };
171
172 if (space <= 0) { //end
173
174 obj[key] = end + u;
175
176 if (endFn) { endFn() };
177
178 return;
179
180 };
181
182 } else {
183
184 if (space > length / 3) {
185
186 speed = Math.floor(space / 3);
187
188 };
189
190 if (space >= 0) { //end
191
192 obj[key] = end + u;
193
194 if (endFn) { endFn() };
195
196 return;
197
198 };
199
200 };
201
202 obj[key] = now + u;
203
204 obj['_extend_actPX' + key.replace(/\-\.\=/, '_') + '_timeOut'] = setTimeout(arguments.callee, 20);
205
206 }, 20);
207
208 }
209
210 }
211
212 }
213 };

页面中现实列表的主题框架如下:

View Code
1 <div id="parMain" class="parMainCss">
2 <div id="pL_Main" class="pL_MainCss">
3 <div id="search_out">
4 </div>
5 </div>
6 </div>

下面看看如何实现滑动翻页,思路:当手指触摸屏幕的时候捕获touchstart事件并记录下手指的坐标,滑动时捕获touchmove事件同时检测是否是有多根手指,手指离开屏幕时捕获touchend事件记录离开时的坐标,并于touchstart时的坐标比较,确定翻页动作。

View Code
  1 material.iPad = {
2
3 x: 0,
4 y: 0,
5
6 lastX: 0,
7 lastY: 0,
8
9 status: 'ok',
10 alertStatus: 'close',
11
12 init: function () {
13
14 if (!/\((iPhone|iPad|iPod)/i.test(navigator.userAgent)) { return };
15 var tempThis = this;
16 var iPadCSS = document.createElement('style');
17 document.getElementsByTagName('head')[0].appendChild(iPadCSS);
18 iPadCSS.textContent = '.iPadAlertPage{width:300px;text-align:center;color:#333;position:absolute;font-size:20px;padding:20px 0;border:2px solid #999;background:#ccc;}';
19
20 Commom.delEvent(Commom.$get('pL_Main'), 'touchstart', tempThis._touchstart);
21 Commom.delEvent(Commom.$get('pL_Main'), 'touchmove', tempThis._touchmove);
22 Commom.delEvent(Commom.$get('pL_Main'), 'touchend', tempThis._touchend);
23
24 Commom.addEvent(Commom.$get('pL_Main'), 'touchstart', function (e) { tempThis._touchstart(e) });
25 Commom.addEvent(Commom.$get('pL_Main'), 'touchmove', function (e) { tempThis._touchmove(e) });
26 Commom.addEvent(Commom.$get('pL_Main'), 'touchend', function (e) { tempThis._touchend(e) });
27 },
28
29 showAlertPage: function (num) {
30 var tempThis = this;
31 if (!this.showAlertDivPage) {
32 this.showAlertDivPage = document.createElement('div');
33 Commom.$get('parMain').appendChild(this.showAlertDivPage);
34 this.showAlertDivPage.onclick = function () {
35 tempThis.hideAlert();
36 };
37
38 };
39
40 this.showAlertDivPage.className = 'iPadAlertPage';
41 this.showAlertDivPage.style.top = window.pageYOffset + Math.round(Commom.$get('parMain').offsetHeight / 2) + 'px';
42 this.showAlertDivPage.style.left = window.pageXOffset + Math.round(Commom.$get('parMain').offsetWidth / 2) + 'px';
43 this.showAlertDivPage.style.opacity = 0.7;
44 this.showAlertDivPage.style.display = 'block';
45 this.showAlertDivPage.innerHTML = 'Loading page: ' + num;//加载的页码,
46 setTimeout(function () { tempThis.hideAlertPage() }, 1000);
47 },
48
49 hideAlertPage: function () {
50 Commom.extend.hide(this.showAlertDivPage);
51 },
52
53 _touchstart: function (e) {
54 this.x = e.touches[0].pageX;
55 this.scrollX = window.pageXOffset;
56 this.scrollY = window.pageYOffset; //用于判断页面是否滚动
57 },
58
59 _touchmove: function (e) {
60 if (e.touches.length > 1) { //多点触摸
61 this.status = 'ok';
62 return;
63 };
64
65 this.lastX = e.touches[0].pageX;
66 var cX = this.x - this.lastX;
67 if (cX < 0) {
68 //第一页禁止向左
69 };
70
71 if (this.status == 'ok') {
72 if (this.scrollY == window.pageYOffset && this.scrollX == window.pageXOffset && Math.abs(cX) > 50) { //横向触摸
73 if (cX > 0) {
74 //最后一页禁止向右
75 };
76 this.status = 'touch';
77 } else {
78 return;
79 };
80 };
81
82 Commom.$get('search_out').style.marginLeft = -cX + 'px'; //设置列表移动横坐标
83 e.preventDefault();
84 },
85
86 _touchend: function (e) {
87
88 if (this.status != 'touch') { return };
89 this.status = 'ok';
90 var cX = this.x - this.lastX;
91 var tempThis = this;
92 if (this.alertStatus == 'open') { this.hideAlert() };
93 Commom.extend.actPX(Commom.$get('search_out').style, 'marginLeft', Commom.$get('search_out').offsetLeft, cX > 0 ? -Commom.$get('search_out').offsetWidth : Commom.$get('search_out').offsetWidth, 200, function () {
94 if (cX < 0) {
95 //此处上一页操作
96 } else {
97 //此处下一页操作
98 };
99 tempThis.showAlertPage(index);//显示当前正在加载的页数
100 Commom.$get('search_out').style.marginLeft = 0; //还原列表位置
101 });
102 }
103
104 };
至此即完成滑动翻页的关键步骤了。