可能咋一看不知道我說的是個啥,因為ios本來就用這功能的啊,還類比它幹啥?先聽我說下項目背景哈
我現在開發的是一個webapp,主要是用在ipad上,這個app的大小是固定大小的,為了防止觸摸它出現彈性滾動,我加個句代碼:
$(document).bind('touchmove', function(e) { e.preventDefault();});
這樣這個頁面就被我鎖死了,不會出現討厭的彈性滾動了,再加上一些meta屬性(我的blog裡有這些)全屏啥的,基本上跟nativeapp無異了。
但是呢,問題出來了,裡面有個div裡面內容比較多,需要用到捲軸,現在的問題是,我的網頁裡設定這個div的overflow為scroll後,觸摸這個div不能滾動了!我先試著把上面的代碼注釋點,發現可以滾動了,但是效果很差,沒有ios內建的那種手離開後還會滾動一會的那種“刹車”的效果,於是呢,就想著自己搞一個出來,於是就寫了一個jquery外掛程式,實現了上下左右滑動和輕拍(因為點擊事件在ipad上有半秒延遲),下面會有。關於滾動效果呢,是我花了一整天時間研究出來的,覺得收穫很大,所以拿出來跟大家分享下,以下是一些核心代碼:
(function show(time){if(!source.animation){return;}source.animation = window.setTimeout(function(){if(time > 90){ return; }X && $self.scrollLeft($self.scrollLeft() - ha(time,speedX) * aa );Y && $self.scrollTop($self.scrollTop() - ha(time,speedY) * aa );show(++time);},aa);})(1);
函數ha:
function ha(x,maxSpeed){//return maxSpeed / x;//y = 100 / x;//return maxSpeed - maxSpeed / 100 * x;// y = -x + 100;return (1 - Math.sqrt(10000-(x-100)*(x-100)) / 100) * maxSpeed ;//y = -sqrt(10000-(x-100)2) + 100}
上面第一段代碼的意思是在手指離開螢幕之後要執行的一個連續動畫,可以看到,隨著時間速度越來越慢,速度的變化由函數ha決定,一開始我用y = 1/x的速度,發現速度變化太快,動畫執行完一半就基本上等於結束了,後來就是在慢慢的蹭一秒多,縣的很不流暢。。然後就換,換成了第二個,y = -x + 100,這個效果好一點了,但是太流暢了。。刷一下飛好遠。。用aa調整靈敏度後效果還是差強人意,於是看了半天蘋果內建的效果,發現速度在由快變慢的過程中,加速度絕對值的變化程度好像是小--大--小的一個狀態,於是我就試著用y
= x2 - 10x(具體多少忘記了)之類的函數去試,效果還好,不過還是有點快,最後我選中了四分之一圓,這個弧度性感又均衡,在靈敏度調整為20後,終於實現了和ios相差無幾的滾動效果,心裡那個高興啊。。呵呵,。
由於代碼不長,就直接貼這裡了,簡單的API如下:
$(selecor).swipeleft(fn).swiperight(fn).swipeup(fn).swipedown(fn).tap(fn).scrollX().scrollY().scroll('xy');注意滾動和swipe會衝突,盡量避免一起使用~
jQueqy.tomTouch.js
(function($){//if (!document.documentElement.ontouchstart){return;}var events = "touchmove,tap,swiperight,swipeleft,swipeup,swipedown";var proto = function($e,type,fn){this.$e = $e;this.type = type;this.fn = fn;};proto.prototype = {swipeDistance:40,startX:0,startY:0,tempX:0,tempY:0,startTime:undefined,animation:undefined,touchmove:function(e){var self = e.data;e = e.originalEvent;if (e.targetTouches.length >= 1) {var touch = e.targetTouches[0];if(self._touchmove){self.fn.touchmove.call(this,{deltaX:touch.pageX - self.tempX,deltaY:touch.pageY - self.tempY,x:touch.pageX,y:touch.pageY,tomSource:self});}self.tempX = touch.pageX;self.tempY = touch.pageY;}},touchstart:function(e){var self = e.data;e = e.originalEvent;if (e.targetTouches.length >= 1) {var touch = e.targetTouches[0];self.tempX = self.startX = touch.pageX;self.tempY = self.startY = touch.pageY;self.animation = undefined;self.startTime = +new Date;self.fn.touchstart && self.fn.touchstart.call(this,{x:e.pageX,y:e.pageY,tomSource:self});}},touchend:function(e){var self = e.data;e = e.originalEvent;if (e.changedTouches.length >= 1) {self.animation = true;var touch = e.changedTouches[0] ,now = +new Date() ,dX = touch.pageX - self.startX ,dY = touch.pageY - self.startY ,AdX = Math.abs(dX) ,AdY = Math.abs(dY) ,timeD = now - self.startTime; if((timeD < 100 && AdX < 15 && AdY < 15 && self._tap) || (dX > self.swipeDistance && AdX > AdY && self._swiperight) ||(-dX > self.swipeDistance && AdX > AdY && self._swipeleft) ||(dY > self.swipeDistance && AdY > AdX && self._swipedown) ||(-dY > self.swipeDistance && AdY > AdX && self._swipeup)){self.fn.call(this,{});}var speedX = dX / timeD;var speedY = dY / timeD;//d(self.startY + "," + touch.pageY);self.fn.touchend &&self.fn.touchend.call(this,{x:touch.pageX,y:touch.pageY,speedX:speedX,speedY:speedY,tomSource:self});}},handle:function(){var self = this;$.each(events.split(','),function(i,item){if(item == self.type){self[ "_" + item ] = true;}});self.$e.bind("touchmove",self,self.touchmove);self.$e.bind("touchstart",self,self.touchstart);self.$e.bind("touchend",self,self.touchend);}};$.each(events.split(","),function(i,name){$.fn[name] = function(fn){var touches = new proto($(this),name,fn);touches.handle();return $(this);}});$.fn.touchScroll = function(direction){var X = /x/gi.test(direction) ,Y = /y/gi.test(direction) ,self = this ;$(this).touchmove({touchmove:function(ex){X && $(this).scrollLeft($(this).scrollLeft() - ex.deltaX);Y && $(this).scrollTop($(this).scrollTop() - ex.deltaY);},touchend:function(e){var $self = $(this) ,timeDuration = 3000 ,aa = 20 ,speedX = e.speedX ,speedY = e.speedY ,source = e.tomSource ;//d(speedY);///*(function show(time){if(!source.animation){return;}source.animation = window.setTimeout(function(){if(time > 90){ return; }X && $self.scrollLeft($self.scrollLeft() - ha(time,speedX) * aa );Y && $self.scrollTop($self.scrollTop() - ha(time,speedY) * aa );show(++time);},aa);})(1);function ha(x,maxSpeed){//return maxSpeed / x;//y = 100 / x;//return maxSpeed - maxSpeed / 100 * x;// y = -x + 100;return (1 - Math.sqrt(10000-(x-100)*(x-100)) / 100) * maxSpeed ;//y = -sqrt(10000-(x-100)2) + 100}}});return $(this);}$.fn.touchScrollX = function(){$(this).touchScroll("x");};$.fn.touchScrollY = function(){$(this).touchScroll("y");};})(jQuery);