摘要:鎖滾動(dòng)問題近日做需求,發(fā)現(xiàn)一個(gè)常用插件突然出毛病了,于是探究了一番個(gè)中原因。但在最新版下,準(zhǔn)確的說是系統(tǒng)環(huán)境下,發(fā)生了自定義滾動(dòng)條鎖滾動(dòng)的問題。是通過監(jiān)聽頁面滾輪事件,進(jìn)一步進(jìn)行設(shè)置內(nèi)容位置來實(shí)現(xiàn)自定義滾動(dòng)條的。
tinyscrollbar鎖滾動(dòng)問題
近日做需求,發(fā)現(xiàn)一個(gè)常用插件jquery.tinyscrollbar突然出毛病了,于是探究了一番個(gè)中原因。
出問題的場(chǎng)景在ie,chrome以及其他主流瀏覽器下,jquery.tinyscrollbar能夠正常響應(yīng)并滾動(dòng)自定義滾動(dòng)條。但在最新版firefox下,準(zhǔn)確的說是OS X系統(tǒng)環(huán)境下,發(fā)生了自定義滾動(dòng)條鎖滾動(dòng)的問題。
尋找問題源頭我們發(fā)現(xiàn)場(chǎng)景下,是滾動(dòng)了一段距離后,插件突然卡住。
于是我開始翻閱jquery.tinyscrollbar的源碼,尋找設(shè)置內(nèi)容位置的代碼。jquery.tinyscrollbar是通過監(jiān)聽頁面滾輪事件,進(jìn)一步進(jìn)行設(shè)置內(nèi)容位置來實(shí)現(xiàn)自定義滾動(dòng)條的。其中響應(yīng)滾動(dòng)事件的方法是_wheel,那好,我們來看_wheel的源碼
通過閱讀jquery.tinyscrollbar源碼發(fā)現(xiàn),有一段源碼是如此陳述的:
/** * @method _wheel * @private */ function _wheel(event) { if(self.hasContentToSroll) { // Trying to make sense of all the different wheel event implementations.. // 接洽原生事件 var evntObj = event || window.event // 獲取滾輪的差量 , wheelDelta = -(evntObj.deltaY || evntObj.detail || (-1 / 3 * evntObj.wheelDelta)) / 40 // 獲取滾動(dòng)單位 , multiply = (evntObj.deltaMode === 1) ? self.options.wheelSpeed : 1 ; // 計(jì)算內(nèi)容位置 self.contentPosition -= wheelDelta * multiply * self.options.wheelSpeed; self.contentPosition = Math.min((self.contentSize - self.viewportSize), Math.max(0, self.contentPosition)); // 計(jì)算滾動(dòng)條位置 self.thumbPosition = self.contentPosition / self.trackRatio; /** * The move event will trigger when the carousel slides to a new slide. * 向外拋出移動(dòng)事件 * @event move */ $container.trigger("move"); // 設(shè)置滾動(dòng)條位置 $thumb.css(posiLabel, self.thumbPosition); // 設(shè)置內(nèi)容位置 $overview.css(posiLabel, -self.contentPosition); // 判斷是否觸底,觸底的話阻止事件繼續(xù)觸發(fā) if(self.options.wheelLock || _isAtBegin() && _isAtEnd()) { evntObj = $.event.fix(evntObj); evntObj.preventDefault(); } if(_isAtBegin() && _isAtEnd()){ evntObj.stopPropagation(); } } }
既然是內(nèi)容滾不動(dòng)了,那么問題一定出在設(shè)置內(nèi)容位置的地方了
確定問題我們?cè)谶@個(gè)方法里對(duì)self.contentPosition打了個(gè)log,果不其然,self.contentPosition顯示為NaN。要知道NaN和任何數(shù)做計(jì)算最后所得的值都是NaN的,所以出現(xiàn)了bug。
那么這個(gè)NaN是哪里來的呢?繼續(xù)對(duì)wheelDelta和multiply打log,發(fā)現(xiàn)wheelDelta產(chǎn)生了NaN值。
此時(shí)一頭黑人問號(hào)。近一步翻閱MDN發(fā)現(xiàn),大部分現(xiàn)代瀏覽器支持wheel事件(DOM Level 2的事件),ie和webkit瀏覽器支持mousewheel事件(非標(biāo)準(zhǔn)),老的火狐瀏覽器支持的是DOMMouseScroll事件(非標(biāo)準(zhǔn))。于是我們開始探究幾個(gè)事件中的差異
wheel事件所具有的read-only屬性
WheelEvent.deltaX 雙精度值,表示滾輪在水平方向的差量 WheelEvent.deltaY 雙精度值,表示滾輪在豎直方向的差量 WheelEvent.deltaZ 雙精度值,表示滾輪在z軸上的差量 WheelEvent.deltaMode 無符號(hào)長(zhǎng)整形,表示滾動(dòng)的單位, 0為表示px,1為表示以行為單位滾動(dòng),2為以頁為單位滾動(dòng)
wheel事件同時(shí)繼承了父類MouseEvent, UIEvent 和 Event的屬性
UIEvent.detail 返回一個(gè)長(zhǎng)整型數(shù)值,用于描述該事件,依賴于事件類型
delta的值并不代表真實(shí)的滾動(dòng)量,只是針對(duì)鼠標(biāo)指針的位置來計(jì)算的
MouseWheelEvent read-only屬性
wheelDelta 長(zhǎng)整型,以像素來計(jì)算的滾輪偏移值 wheelDeltaX 長(zhǎng)整型,以像素來計(jì)算的滾輪x軸偏移值 wheelDeltaY 長(zhǎng)整型,以像素來計(jì)算的滾輪y軸偏移值 detail 該值總是0,除了Opera瀏覽器以外
DOMMouseScroll只有一個(gè)屬性
detail 用于精確描述滾動(dòng),正值表示向下滾,負(fù)值表示向上滾。向上滾一頁-32768,向下滾一頁32768,其他值表示滾動(dòng)行數(shù) 重要描述,該值永遠(yuǎn)不為0
detail值的描述
在MouseWheelEvent中,
Opera設(shè)置這個(gè)值和firefox的Gecko內(nèi)核DOMMouseScroll 事件的 detail是一樣的。都用來表示以行來滾動(dòng),負(fù)值用來表示向底部或者向右滾動(dòng)。在mac上,滾動(dòng)加速階段會(huì)計(jì)算該值。在linux上,是由原生滾動(dòng)事件設(shè)置的,值為2或者-2
所以新版firefox中wheel事件發(fā)生了啥?我們打印console.log(evt.deltaX,event.detail,event.wheelDelta)。發(fā)現(xiàn)在觸底的時(shí)候,日志顯示(0,0,undefined),真相大白!
在webkit或者blink中,deltaX這個(gè)值永遠(yuǎn)不會(huì)被設(shè)置為0,而在新版firefox中(mac os x),這個(gè)值在某時(shí)阻尼滾動(dòng)結(jié)束的時(shí)候是會(huì)變?yōu)?0。由于下式的斷言,最終整個(gè)計(jì)算中被引入了一個(gè)NaN
wheelDelta = -(evntObj.deltaY || evntObj.detail || (-1 / 3 * evntObj.wheelDelta)) / 40是插件的缺陷嗎
很明顯,插件作者最初是沒有設(shè)想到deltaY為0的情況,于是依托或運(yùn)算的截?cái)嗖僮鲗懥诉@句經(jīng)驗(yàn)而來的代碼。對(duì)我們這些工作者而言,這樣的判斷是不嚴(yán)謹(jǐn)?shù)摹H绻麌?yán)格按照瀏覽器的區(qū)分來判斷,就能避免這個(gè)問題。以測(cè)試而言,明顯作者沒有考慮到undefined這樣的極端情況。
作者去哪兒啦?在git上尋找作者,發(fā)現(xiàn)該倉庫已經(jīng)年久失修了。。。作者棄坑而去
解決辦法臨時(shí)的:
自己把插件源碼改了,將默認(rèn)值設(shè)為0,避免NaN引入的風(fēng)險(xiǎn)wheelDelta = -(evntObj.deltaY || evntObj.detail || (-1 / 3 * evntObj.wheelDelta)) / 40 || 0
永久的:
向火狐提issue~
可能實(shí)現(xiàn)的(極?。?br> 向作者提pr
一切按標(biāo)準(zhǔn)或者文檔來(MSDN有時(shí)候不可信,佐證如下)
Interface :MouseWheelEvent Synchronicity :asynchronous Bubbles : yes (Though, MSDN documents "No") Target :Element, Document, Window Cancelable : yes (Though, MSDN documents "No") Default action : Scroll, moving history, or zooming in/outMDN賽高!
MDN目前已經(jīng)變成最大的web標(biāo)準(zhǔn),文檔集散地了
參考資料MouseWheelEvent
DomMouseScrollEvent
WheelEvent
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/89367.html
摘要:本插件是對(duì)插件的一個(gè)封裝。因?yàn)樵谟玫臅r(shí)候需要同時(shí)引用和文件,同時(shí)還需要修改結(jié)構(gòu),比較麻煩,為了方便起見,將和文件都用引入,修改的方法也放在文件中。具體代碼使用方法引入文件引入文件初始化滾動(dòng)條為內(nèi)容容器的主要的代碼如下創(chuàng)建文本片段 本插件是對(duì)tinyscrollbar插件的一個(gè)封裝。因?yàn)樵谟玫臅r(shí)候需要同時(shí)引用css和js文件,同時(shí)還需要修改dom結(jié)構(gòu),比較麻煩,為了方便起見,將tinys...
摘要:下面正式推薦大神的博文前段時(shí)間使用做滾動(dòng)條控件,添加滾輪事件時(shí),查閱了一些資料,發(fā)現(xiàn)大都是文檔描述或簡(jiǎn)單示例,對(duì)于開發(fā)者還是不夠。一測(cè)試目標(biāo)探索事件中常用屬性的有效性,垂直步進(jìn)算法滑動(dòng)幅度以及與電腦個(gè)性化設(shè)置的關(guān)聯(lián)。 最近在用VUE寫一個(gè)后臺(tái)管理系統(tǒng),頂部標(biāo)簽頁涉及鼠標(biāo)滾輪事件,由于每個(gè)瀏覽器對(duì)滾輪事件的處理方式不一樣,個(gè)人對(duì)這個(gè)又不懂,折騰了很久,參考了大神的代碼,也把百度翻爛了,找...
摘要:場(chǎng)景當(dāng)頁面出現(xiàn)浮層的時(shí)候,滑動(dòng)浮層的內(nèi)容,正常情況下預(yù)期應(yīng)該是浮層下邊的內(nèi)容不會(huì)滾動(dòng)然而事實(shí)并非如此。當(dāng)屬性的值為的時(shí)候,代表該監(jiān)聽器內(nèi)部不會(huì)調(diào)用函數(shù)來阻止默認(rèn)滑動(dòng)行為,瀏覽器稱這類型的監(jiān)聽器為被動(dòng)監(jiān)聽器。 場(chǎng)景 當(dāng)頁面出現(xiàn)浮層的時(shí)候,滑動(dòng)浮層的內(nèi)容,正常情況下預(yù)期應(yīng)該是浮層下邊的內(nèi)容不會(huì)滾動(dòng);然而事實(shí)并非如此。showImg(https://user-gold-cdn.xitu.io...
摘要:場(chǎng)景當(dāng)頁面出現(xiàn)浮層的時(shí)候,滑動(dòng)浮層的內(nèi)容,正常情況下預(yù)期應(yīng)該是浮層下邊的內(nèi)容不會(huì)滾動(dòng)然而事實(shí)并非如此。當(dāng)屬性的值為的時(shí)候,代表該監(jiān)聽器內(nèi)部不會(huì)調(diào)用函數(shù)來阻止默認(rèn)滑動(dòng)行為,瀏覽器稱這類型的監(jiān)聽器為被動(dòng)監(jiān)聽器。 場(chǎng)景 當(dāng)頁面出現(xiàn)浮層的時(shí)候,滑動(dòng)浮層的內(nèi)容,正常情況下預(yù)期應(yīng)該是浮層下邊的內(nèi)容不會(huì)滾動(dòng);然而事實(shí)并非如此。showImg(https://user-gold-cdn.xitu.io...
閱讀 1318·2021-11-22 14:44
閱讀 2461·2021-09-30 09:47
閱讀 1231·2021-09-09 11:56
閱讀 2095·2021-09-08 09:45
閱讀 4004·2021-08-31 09:40
閱讀 1265·2019-08-30 15:52
閱讀 2053·2019-08-30 14:09
閱讀 1599·2019-08-26 17:04