<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
專案實現過程中需要對一個已經有縱向卷軸的table表格增加滑鼠滾輪(mousewheel)事件,方便檢視資料;其實現原理與我上一篇部落格中的拖動事件類似,利用模擬出來的同一個卷軸來實現
1、卷軸與捲動槽的高度比例 應該等於 內容區(動態變化)和可視區的高度比例;捲動槽與可視區平齊,高度一樣;卷軸的高度則根據內容的高度等比例計算;
2、各元素的定位採用絕對定位,其父元素採用相對定位,這樣就能很好地設定樣式;
佈局與樣式做好後,只需要在元件methods註冊方法,在元素就位後呼叫該方法,在方法內部為表格繫結(mousewheel)事件;在這裡需要考慮相容性問題,firefox並不支援mousewheel事件,它對應的滑鼠捲動事件為DOMMouseScroll事件,並且該事件僅能通過DOM2級(addEventListener)新增處理程式;並且判斷滑鼠捲動方向的方式也不一樣,firefoxt通過detail屬性判斷,向前捲動該屬性為-3,向後+3;其餘瀏覽器通過wheelDelta屬性,向前時為+120的倍數,向後為-120的倍數;
具體內容可參考《js高階程式設計》事件一章;新增函數如下:
scroll(){ this.wrapDiv = document.getElementById("wrap"); this.contentDiv = document.getElementById("context-table"); this.contentDiv1 = document.getElementById("context-table1"); this.sliderWrap = document.getElementById("sliderWrap"); this.slider = document.getElementById("slider"); //設定比例 let scale = this.wrapDiv.clientHeight / this.contentDiv.clientHeight; if (scale < 1) { this.mouseFlag = true; let h1 = this.sliderWrap.clientHeight * scale; h1 = (h1 < 50) ? 50 : h1; this.slider.style.height = h1 + "px";/*卷軸高度動態變化*/ let y = 0; let that = this; //為firefox新增滾輪事件 if (document.addEventListener){ document.addEventListener('DOMMouseScroll',function (e) { if(that.mouseFlag){ //console.log('scroll'); let event1 = window.event|| e; y = (event1.detail > 0) ? y + 8 : y - 8; y = (y < 0) ? 0 : y; let max = that.sliderWrap.clientHeight - that.slider.clientHeight; y = (y > max + 1) ? max + 1 : y; that.slider.style.top = y + "px"; scale = that.wrapDiv.clientHeight / that.contentDiv.clientHeight; let y1 = -y / scale; that.contentDiv.style.top = y1 + "px"; that.contentDiv1.style.top = y1 + "px"; } },false) } this.wrapDiv.onmousewheel = function (e) { if (scale < 1) { let event1 = window.event || e; y = (event1.wheelDelta < 0) ? y + 8 : y - 8; y = (y < 0) ? 0 : y;/*限定捲動範圍*/ let max = that.sliderWrap.clientHeight - that.slider.clientHeight; //console.log(scale, y, sliderWrap.clientHeight, slider.clientHeight); y = (y > max + 1) ? max + 1 : y; that.slider.style.top = y + "px"; scale = that.wrapDiv.clientHeight / that.contentDiv.clientHeight; let y1 = -y / scale; that.contentDiv.style.top = y1 + "px"; that.contentDiv1.style.top = y1 + "px"; } } } else{/*當內容區高度小於等於可視區時,去除繫結的事件和卷軸*/ this.wrapDiv.onmousewheel =null; if(document.addEventListener){ this.mouseFlag = false; } this.sliderWrap.style.visibility = 'hidden'; let height = this.contentDiv.clientHeight; tableRight.style.height = height+72+'px'; this.wrapDiv.style.height = height+2+'px'; } },
該函數在給firefox繫結的事件解綁時遇到了問題,由於removeEventListener()需要通過控制程式碼來解綁,而addEventListener()通過控制程式碼新增處理常式會導致event引數無法傳遞的問題;即使在需要解綁時給document繫結空的處理常式也無法覆蓋前一個繫結函數;最後只好新增一個標誌,在需要解綁函數時改變標誌的值;在繫結函數中通過判斷該標誌的值來確定是否要做操作;
通過上述方式即可很好地實現滑鼠捲動事件的效果,並不會有相容性的問題出現。
注:若僅僅是為表格繫結單一的捲動事件,則可以不顯示卷軸,甚至不設定卷軸;卷軸的作用僅僅是用來指示內容區捲動的位置,以及配合拖動事件使用;
火狐的滑鼠滾輪事件是DOMMouseScroll
事件引數相容:e=window.event||e;(下面省略)
preventDefault()函數取消的是預設事件,不會把我們自己新增的事件處理刪除
在下面驗證例子的基礎上實驗,實驗之間程式碼沒有干涉:
1.原樣輸出
在元素內無論是手動拉動卷軸還是捲動滑鼠滾輪,'d'都是無法出現的。而當元素捲動到達頂部或底部的時候,輸出的是就有'd'了,但是這個時候並沒有輸出'b',說明scroll事件本來就沒有發生冒泡。而document的scroll事件是由於其他因素觸發的。
2.在element的mousewheel事件處理裡把冒泡取消
e.stopPropagation();
這時候在元素內捲動滑鼠滾輪,'c'始終是無法出現的,說明我們阻止mousewheel事件的冒泡成功了。但是在卷軸到達底部或頂部時,雖然'c'依舊沒有出現,但是'd'卻出現了,說明這個時候的document的scroll事件是靠element的mousewheel來觸發的。
到這裡就出現一個問題:element的mousewheel事件在預設處理裡對這一情形進行了處理嗎?
3.在element的mousewheel事件處理裡取消預設處理
e.preventDefault();
這時候在元素內捲動滑鼠,只會有'a'、'c'會出現,頁面也不會捲動。說明滑鼠滾輪捲動element頁面的效果是由element的mousewheel預設事件處理來的。這個時候留意實驗1中滾輪捲動一下'b'的輸出數量,大概就能猜到預設處理的過程。
4.在element的mousewheel裡新增一個自己的頁面捲動(與預設處理的捲動方向相反)
element.scrollTop+=e.wheelDelta>0?30:-30;//手動新增的頁面捲動
這個時候在元素內捲動滑鼠,你會發現即使捲動到頂部或底部,元素外的頁面並不會捲動,且並沒有輸出'd',也就是document的scroll事件沒有觸發。不好的一點是你在捲動到底部或頂部時,繼續捲動滑鼠的話,元素內還是會捲動,只不過是先下再上(或先上再下)地波動一下。
5.在element的mousewheel裡新增一個自己的頁面捲動(與預設處理的捲動方向相同)
element.scrollTop+=e.wheelDelta<0?30:-30;//手動新增的頁面捲動
這個時候在元素內捲動滑鼠,你會發現即使捲動到頂部或底部,元素外的頁面跟著捲動,且輸出'd',也就是document的scroll事件觸發了。
這裡需要注意到一點:元素的scrollTop屬性是無法無限增加和減少的,到了捲動的頂部或底部後只能反向變化(可以自行輸出測試)。
6.在實驗5的基礎上,將捲動的距離調整到很大
element.scrollTop+=e.wheelDelta<0?300:-300;(值要大等於捲動行程)
認真觀察輸出的'b'的個數,和實驗1的對比,你會發現這次只有1個'b',而且還輸出了'd',而且'd'的數量還不少。經過一些其他的實驗,得到:預設事件處理裡的判斷大概如下:
(function scroll(element){ for(var i=0;i<12;i++){ var temp=element.scrollTop; element.scrollTop+=e.wheelDelta<0?10:-10; //捲動演演算法肯定不是這個,這裡只是簡單演示 if(temp!= element.scrollTop){ //捲動‘訊息樹'的下一個元素(和冒泡是一個列表) var newEle=....//訊息樹怎麼獲取我不懂 scroll(newEle); return; } } })();
驗證例子:
addEventListener(element,'mousewheel',function(e){ console.log('a'); }); addEventListener(element,'scroll',function(e){ console.log('b'); }); addEventListener(document.documentElement,'mousewheel',function(e){ console.log('c'); }); addEventListener(document,'scroll',function(e){ console.log('d'); });
結論:通過上面的6個實驗,很容易發現在元素的mousewheel的預設處理事件裡對scrollTop屬性進行變化和判斷,如果沒有發生變化就對外部元素進行卷動一下(具體捲動演演算法不懂,捲動距離和滑鼠滾一下是一樣的),以此類推,如果下一個元素到邊界了,就再下一個。而這個過程和冒泡是沒有關係的,只是當前元素的mousewheel預設事件處理進行的。
應用:因此為了實現元素捲動到底時繼續捲動卻不會使外部元素捲動,我們可以直接取消它的預設處理,然後給一個自己的捲動函數就可以了。至於怎麼滾就看自己給什麼函數了,而冒泡取不取消也看自己,上面的預設處理在冒泡和捕獲階段是不進行的。
例子如下:
addEventListener(element,'mousewheel',function(e){ console.log('a'); e.preventDefault(); // e.stopPropagation(); ulObj.scrollTop+=e.wheelDelta<0?20:-20; }); addEventListener(element,'scroll',function(e){ console.log('b'); }); addEventListener(document.documentElement,'mousewheel',function(e){ console.log('c'); }); addEventListener(document,'scroll',function(e){ console.log('d'); });
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45