JS+CSS3模擬溢出滾動效果
移動開發(fā)的時候,我們經(jīng)常會遇到滑動事件,眾所周知手機(jī)端滑動主要依靠touch事件。最近接連遇到兩個頁面都有類似overflow:auto的效果,一般情況下通過css設(shè)置是可以實(shí)現(xiàn)的(雖說丑了點(diǎn)兒),,但是一旦overflow:auto的元素響應(yīng)touch事件時就會有諸多不便,例如fullpage中某一元素自滑動,我們可以通過normalScrollElements來使元素滑動的時候不滑動到下一屏,但是在元素滑動到最底部的時候也就不能響應(yīng)下一屏事件,上滑也是一樣,這時候就需要touch事件來響應(yīng),為了以后封裝方便,特簡單封裝一個jquery插件,同時也復(fù)習(xí)一下jquery插件開發(fā)及touch事件;
插件大體思路是這樣的,如下圖所示:方框內(nèi)區(qū)域為固定寬高的父元素(設(shè)置overflow:hidden),子元素高度大于父元素,我們通過響應(yīng)touch事件改變子元素的translate值(top也可以,但是translate效率更高一些),當(dāng)然在此期間我們需判斷子元素translate值的邊界,最大為0,最小為子元素高度-父元素高度
ps:如果想做子元素根據(jù)手指移動,松開手指后回到邊界需另寫程序
下面來一步步寫插件
第一步,先建立一個安全的作用域
;(function($){ //插入代碼 })(jQuery) 如果我們需要通過$(“#id”).xx()方法調(diào)用,需要像下面這樣寫,這里的fn及jquery的prototype; $.extend({ exec:function(){} }) //這種擴(kuò)展通過$.exec()調(diào)用 $.fn.simuScroll = function(option){ var scrollObj=new simuScroll(this,option); return scrollObj.init(); }
下面來看上面代碼中的simuScroll方法,這是一個構(gòu)造函數(shù),它接受兩個參數(shù),ele為當(dāng)前接受touch事件的元素(一般可以設(shè)置為父元素),option為用戶傳入的配置參數(shù),如改變translate的元素,父元素子元素高度,extra為需額外增加的高度,滑動到頂部或底部時執(zhí)行的回調(diào)函數(shù)等等;
var simuScroll = function(ele,option){ this.settings = { target : ele, //事件元素 changeTarget:'', outerHeight : '800', //外層高度 innerHeight : '500', //內(nèi)層高度 extra : '0', //額外增加的距離 swipeUp : null, swipeDown : null, vertical:true }; //通過jquery.extend對默認(rèn)的settings進(jìn)行擴(kuò)展,得出一個全新的對象 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進(jìn)行擴(kuò)展時,第一步為實(shí)例化上面的構(gòu)造函數(shù),第二步則直接調(diào)用了構(gòu)造函數(shù)的init方法,具體見下面?zhèn)渥?br />
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); //如果子元素高度大于父元素,則執(zhí)行滑動事件,否則執(zhí)行回調(diào)函數(shù) this.flag = this.diff > 0 ? 'translate' : 'exec'; /*如果元素已設(shè)置transform中 translate,scale,skew,rotate中的任何一項, 則我們再直接設(shè)置transform:translateY(10px)時會覆蓋掉初始設(shè)置的屬性 所以我們通過獲取元素的matrix值既保證原有屬性,又能設(shè)置任意值*/ var cssText = this.opt.changeTarget.css('-webkit-transform'); if(cssText=='none'){ //元素未設(shè)置transform屬性 this.str = this.opt.vertical ? 'translateY' : 'translateX' ; }else{ this.str = cssText ; var reg = /-?\d+\.?\d*/g; //正則表達(dá)式 /*獲取matrix中各參數(shù) 直接獲取到的matrix值為類似matrix(1,0,0,1,0,0) 獲取到的為[1,0,0,1,0,0] 這樣我們就可以隨意的修改某一個值 數(shù)組的第5項為元素的translateX值,第6項為translateY值 */ this.params = this.str.match(reg); this.matrix = this.opt.vertical ? 6 : 5 ; //根據(jù)傳入的參數(shù)確定要修改的值為translateY或tranlateX } var _this = this; //父元素綁定touch事件,傳遞事件對象及context target.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方法相對比較簡單,根據(jù)需要滑動的方向記錄手指接觸屏幕時的初始值
start:function(e,context){ e.preventDefault(); var touches = e.touches[0]; context.initNumber = context.opt.vertical ? touches.pageY : touches.pageX; },
touchmove方法主要根據(jù)手指滑動距離動態(tài)改變元素css屬性,讓元素能夠跟隨手指進(jìn)行移動
setNumber方法只有一句話: this.params.splice(n-1,1,number) 根據(jù)傳入的參數(shù)改變matrix數(shù)組
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; //設(shè)置滑動的最大值和最小值 context.result = context.result > 0 ? 0 : context.result ; context.result = -context.result > context.diff ? -context.diff : context.result; //動態(tài)設(shè)置元素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則判斷釋放時是否需要執(zhí)行回調(diào)函數(shù)
end:function(e,context){ e.preventDefault(); var touches = e.changedTouches[0]; var number = context.opt.vertical ? touches.pageY : touches.pageX, n = number - context.initNumber; //當(dāng)元素滑動距離大于10 并且最初元素translate值為0同時回調(diào)函數(shù)存在,則執(zhí)行回調(diào)函數(shù) 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(); } //將常量設(shè)為結(jié)果值,能保證多次連貫滑動 context.lastNumber = context.result; }
基本上一個簡單的jQuery插件就完成了,框架如下
;(function($){ var a = function(m,n){ //函數(shù)內(nèi)容 }; 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)
調(diào)用時如下:
$(".outer").simuScroll({ 'outerHeight':$(".outer").height(), 'innerHeight':$('.inner').height(), 'changeTarget' : $(".inner"), 'swipeUp' :function(){ console.log('up') }, 'swipeDown' :function(){ console.log('down') }, vertical:true })
以上所述是小編給大家介紹的JS+CSS3模擬溢出滾動效果,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
BootStrap使用file-input插件上傳圖片的方法
這篇文章主要介紹了BootStrap使用file-input插件上傳圖片的方法,bootstrap的圖片上傳框架 file-input 插件非常不錯,下面小編通過本文介紹下這個插件的使用方法,感興趣的朋友一起看看吧2016-09-09JavaScript如何將base64圖片轉(zhuǎn)化為URL格式
這篇文章主要給大家介紹了關(guān)于JavaScript如何將base64圖片轉(zhuǎn)化為URL格式的相關(guān)資料,Base64是一種編碼方式,而不是真正的加密方式,即使算Base64也僅用作一個簡單的加密來保護(hù)某些數(shù)據(jù),而真正的加密通常都比較繁瑣,需要的朋友可以參考下2023-07-07js中substring和substr兩者區(qū)別和使用方法
這篇文章主要介紹了js中substring和substr兩者區(qū)別和使用方法,每一個步驟都有相應(yīng)的文字介紹,感興趣的小伙伴們可以參考一下2015-11-11