移動開發的時候,我們經常會遇到滑動事件,眾所周知手機端滑動主要依靠touch事件。最近接連遇到兩個頁面都有類似overflow:auto的效果,一般情況下通過css設定是可以實現的(雖說醜了點兒),,但是一旦overflow:auto的元素響應touch事件時就會有諸多不便,例如fullpage中某一元素自滑動,我們可以通過normalScrollElements來使元素滑動的時候不滑動到下一屏,但是在元素滑動到最底部的時候也就不能響應下一屏事件,上滑也是一樣,這時候就需要touch事件來響應,為了以後封裝方便,特簡單封裝一個jquery外掛程式,同時也複習一下jquery外掛程式開發及touch事件;
外掛程式大體思路是這樣的,如下圖所示:方框內地區為固定寬高的父元素(設定overflow:hidden),子項目高度大於父元素,我們通過響應touch事件改變子項目的translate值(top也可以,但是translate效率更高一些),當然在此期間我們需判斷子項目translate值的邊界,最大為0,最小為子項目高度-父元素高度
ps:如果想做子項目根據手指移動,鬆開手指後回到邊界需另寫程式
下面來一步步寫外掛程式
第一步,先建立一個安全的範圍
;(function($){//插入代碼})(jQuery) 如果我們需要通過$(“#id”).xx()方法調用,需要像下面這樣寫,這裡的fn及jquery的prototype;$.extend({exec:function(){}}) //這種擴充通過$.exec()調用$.fn.simuScroll = function(option){var scrollObj=new simuScroll(this,option);return scrollObj.init();}
下面來看上面代碼中的simuScroll方法,這是一個建構函式,它接受兩個參數,ele為當前接受touch事件的元素(一般可以設定為父元素),option為使用者傳入的配置參數,如改變translate的元素,父元素子項目高度,extra為需額外增加的高度,滑動到頂部或底部時執行的回呼函數等等;
var simuScroll = function(ele,option){this.settings = {target : ele, //事件元素changeTarget:'',outerHeight : '800', //外層高度innerHeight : '500', //內層高度extra : '0', //額外增加的距離swipeUp : null,swipeDown : null,vertical:true};//通過jquery.extend對預設的settings進行擴充,得出一個全新的對象this.opt = jQuery.extend({},this.settings,option); this.initNumber = this.lastNumber = this.result = 0;this.flag = false;//計算出子項目與父元素距離差,以此來判定元素的最大滑動距離this.diff = parseFloat(this.opt.innerHeight) - parseFloat(this.opt.outerHeight) + parseFloat(this.opt.extra);this.diff = this.diff < 0 ? 0 :this.diff;this.direction = '';};
在對jquery prototype進行擴充時,第一步為執行個體化上面的建構函式,第二步則直接調用了建構函式的init方法,具體見下面備忘
init:function(){//jquery對象直接綁定touch事件擷取event需originalEvent擷取原生對象的event屬性//jquery對象 擷取pagex event.originalEvent.touches[0].pageX //dom對象 event.touches[0].pageX var target = this.opt.target.get(0); //如果子項目高度大於父元素,則執行滑動事件,否則執行回呼函數this.flag = this.diff > 0 ? 'translate' : 'exec';/*如果元素已設定transform中 translate,scale,skew,rotate中的任何一項,則我們再直接設定transform:translateY(10px)時會覆蓋掉初始設定的屬性所以我們通過擷取元素的matrix值既保證原有屬性,又能設定任意值*/var cssText = this.opt.changeTarget.css('-webkit-transform');if(cssText=='none'){ //元素未設定transform屬性this.str = this.opt.vertical ? 'translateY' : 'translateX' ;}else{this.str = cssText ;var reg = /-?\d+\.?\d*/g; //Regex/*擷取matrix中各參數直接擷取到的matrix值為類似matrix(1,0,0,1,0,0)擷取到的為[1,0,0,1,0,0] 這樣我們就可以隨意的修改某一個值數組的第5項為元素的translateX值,第6項為translateY值 */this.params = this.str.match(reg); this.matrix = this.opt.vertical ? 6 : 5 ; //根據傳入的參數確定要修改的值為translateY或tranlateX} var _this = this;//父元素繫結touch事件,傳遞事件對象及contexttarget.addEventListener('touchstart',function(e){_this.start(e,_this)});target.addEventListener('touchmove',function(e){_this.move(e,_this)});target.addEventListener('touchend',function(e){_this.end(e,_this)});}
touchstart方法相對比較簡單,根據需要滑動的方向記錄手指接觸螢幕時的初始值
start:function(e,context){e.preventDefault();var touches = e.touches[0];context.initNumber = context.opt.vertical ? touches.pageY : touches.pageX;},
touchmove方法主要根據手指滑動距離動態改變元素css屬性,讓元素能夠跟隨手指進行移動
setNumber方法只有一句話: this.params.splice(n-1,1,number) 根據傳入的參數改變matrix數組
move:function(e,context){e.preventDefault();var touches = e.touches[0];number = context.opt.vertical ? touches.pageY : touches.pageX;//擷取相對手指觸碰螢幕的變化值var delta = number - context.initNumber;if(context.flag == 'translate'){ //如果需要滑動context.result = context.lastNumber + delta;//設定滑動的最大值和最小值context.result = context.result > 0 ? 0 : context.result ;context.result = -context.result > context.diff ? -context.diff : context.result;//動態設定元素css屬性if(context.matrix){switch (context.matrix) {case 6: context.setNumber(6,context.result)break;case 5:context.setNumber(5,context.result)break;}context.opt.changeTarget.css('-webkit-transform','matrix('+context.params.join(',')+')')}else{context.opt.changeTarget.css('-webkit-transform',context.str+'('+context.result+'px)')}}},
touchend則判斷釋放時是否需要執行回呼函數
end:function(e,context){e.preventDefault();var touches = e.changedTouches[0];var number = context.opt.vertical ? touches.pageY : touches.pageX,n = number - context.initNumber;//當元素滑動距離大於10 並且最初元素translate值為0同時回呼函數存在,則執行回呼函數if(n>10 && context.lastNumber == 0 && context.opt.swipeDown){ context.opt.swipeDown()}else if(n<-10 && context.lastNumber == -context.diff && context.opt.swipeUp){context.opt.swipeUp();}//將常量設為結果值,能保證多次連貫滑動context.lastNumber = context.result;}
基本上一個簡單的jQuery外掛程式就完成了,架構如下
;(function($){var a = function(m,n){//函數內容};a.prototype = {init:function(){},start:function(){},move:function(){},end:function(){},setNumber:function(){}}$.fn.scrol = function(o){var obj = new a(this,o);return obj.init()}})(jQuery)
調用時如下:
$(".outer").simuScroll({'outerHeight':$(".outer").height(),'innerHeight':$('.inner').height(),'changeTarget' : $(".inner"),'swipeUp' :function(){console.log('up')},'swipeDown' :function(){console.log('down')},vertical:true})
以上所述是小編給大家介紹的JS+CSS3類比溢出滾動效果,希望對大家有所協助,如果大家有任何疑問請給我留言,小編會及時回複大家的。在此也非常感謝大家對雲棲社區網站的支援!