91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使用原生JS控制多個滾動條同步跟隨滾動效果

發布時間:2021-06-29 11:01:18 來源:億速云 閱讀:177 作者:小新 欄目:web開發

這篇文章將為大家詳細講解有關如何使用原生JS控制多個滾動條同步跟隨滾動效果,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

在一些支持用 markdown 寫文章的網站,后臺寫作頁面,一般都是支持 markdown 即時預覽的,也就是將整個頁面分成兩部分,左半部分是你輸入的 markdown 文字,右半部分則即時輸出對應的預覽頁面,例如下面就是 CSDN 后臺寫作頁面的 markdown 即時預覽效果:

如何使用原生JS控制多個滾動條同步跟隨滾動效果

本文不是闡述如何從 0 實現這種效果的(后續 很可能 會單出文章,),拋開其他,單看頁面主體中左右兩個容器元素,即 markdown 輸入框元素和預覽顯示框元素

本文要探討的是,當這兩個容器元素的內容都超出了容器高度,即都出現了滾動框的時候,如何在其中一個容器元素滾動時,讓另外一個元素也隨之滾動。

DOM 結構

既然是與滾動條有關,那么首先想到 js 中控制滾動條高度的一個屬性: scrollTop ,只要能控制這個屬性的值,自然也就能控制滾動條的滾動了。

對于以下 DOM 結構:

<div id="container">
 <div class="left"></div>
 <div class="right"></div>
</div>

其中, .left 元素是左半部分輸入框容器元素, .right 元素是右半部分顯示框容器元素, .container 是它們共同的父元素。

由于需要溢出滾動,所以還需要設置一下對應的樣式(只是關鍵樣式,非全部):

#container {
 display: flex;
 border: 1px solid #bbb;
}
.left, .right {
 flex: 1;
 height: 100%;
 word-wrap: break-word;
 overflow-y: scroll;
}

再向 .left.right 元素中塞入足夠的內容,讓二者出現滾動條,就是下面這種效果:

如何使用原生JS控制多個滾動條同步跟隨滾動效果

樣式是出來個大概了,下面就可以在這些 DOM 上進行一系列的操作了。

初次嘗試

大致思路,監聽兩個容器元素的滾動事件,在其中一個元素滾動的時候,獲取這個元素的 scrollTop 屬性的值,同時將此值設置為另外一個滾動元素的 scrollTop 值即可。

例如:

var l=document.querySelector('.left')
var r=document.querySelector('.right')
l.addEventListener('scroll',function(){
 r.scrollTop = l.scrollTop
})

效果如下:

如何使用原生JS控制多個滾動條同步跟隨滾動效果

似乎很不錯,但是現在是不僅想讓右邊跟隨左邊滾動,還想左邊跟隨右邊滾動,于是再加以下代碼:

addEventListener('scroll',function(){
 r.scrollTop = l.scrollTop
})

看上去很不錯,然而,哪有那么簡單的事情。

這個時候你再用鼠標滾輪進行滾動的時候,卻發現滾動得有點吃力,兩個容器元素的滾動似乎被什么阻礙住了,很難滾動。

仔細分析,原因很簡單,當你在左邊滾動的時候,觸發了左邊的滾動事件,于是右邊跟隨滾動,但是與此同時右邊的跟隨滾動也是滾動,于是也觸發了右邊的滾動,于是左邊也要跟隨右邊滾動...然后就進入了一個類似于相互觸發的情況,所以就會發現滾動得很吃力。

解決 scroll 事件同時觸發的問題

想要解決上述問題,暫時有以下兩種方案。

將 scroll 事件換成 mousewheel 事件

由于 scroll 事件不僅會被鼠標主動滾動觸發,同時改變容器元素的 scrollTop 也會觸發,元素的主動滾動其實就是鼠標滾輪觸發的,所以可以將 scroll 事件換成一個對鼠標滾動敏感而不是元素滾動敏感的事件:'mousewheel',于是上述監聽代碼變成了:

addEventListener('mousewheel',function(){
  r.scrollTop = l.scrollTop
})
r.addEventListener('mousewheel',function(){
  l.scrollTop = r.scrollTop
})

效果如下:

如何使用原生JS控制多個滾動條同步跟隨滾動效果

似乎是有點用,但是實際上還有兩個問題。

當滾動其中一個容器元素的時候,另外一個容器元素雖然也跟著滾動,但滾動得并不流暢,高度有明顯的瞬間彈跳

在網上找了一圈,沒有找到關于 wheel 事件滾動頻率相關內容,我推測這可能就是此事件的一個 feature

鼠標每次滾動基本上都并不是以 1px 為單位的,其最小單元遠比 scroll 事件小的多,我用我的鼠標在 chrome 瀏覽器上滾動,每次滾過的距離都恰好是 100px ,不同的鼠標或者瀏覽器這個數值應該都是不一樣的,而 wheel 事件其實真正監聽的是鼠標滾輪滾過一個齒輪卡點的事件,這也就能解釋為何會出現彈跳的現象了。

如何使用原生JS控制多個滾動條同步跟隨滾動效果

一般來說,鼠標滾輪每滾過一個齒輪卡點,就能監聽到一個 wheel 事件,從開始到結束,被鼠標主動滾動的元素已經滾動了 100px ,所以另外一個跟隨滾動的容器元素也就瞬間跳動了 100px

而之所以上述 scroll 事件不會讓跟隨滾動元素出現瞬間彈跳,則是因為跟隨滾動元素每次 scrollTop 發生變化時,其值不會有 100px 那么大的跨度,可能也沒有小到 1px ,但由于其觸發頻率高,滾動跨度小,最起碼在視覺上就是平滑滾動的了。

wheel 只是監聽鼠標滾輪事件,但如果是用鼠標拖動滾動條,就不會觸發此事件,另外的容器元素也就不會跟隨滾動了

這個其實很好解決,用鼠標拖動滾動條肯定是能觸發 scroll 事件的,而在這種情況下,你肯定能夠很輕易地判斷出這個被拖動的滾動條是屬于哪個容器元素的,只需要處理這個容器的滾動事件,另外一個跟隨滾動容器的滾動事件不做處理即可。

wheel 事件的兼容問題

wheel 事件是 DOM Level3 的標準事件,但是除了此事件之外,還有很多非標準事件,不同的瀏覽器內核使用不同的標準,所以可能還需要按情況來進行兼容,具體可見MDN MouseWheelEvent

如何使用原生JS控制多個滾動條同步跟隨滾動效果 實時判斷

如果你難以忍受 wheel 的彈跳,以及各種兼容,那么其實還有另外的路可以走得通,依舊是 scroll 事件,只不過需要做一些額外的工作。

scroll 事件的問題在于,沒有判斷當前主動滾動的是哪一個容器元素,只要確定了主動滾動的容器元素,這事就好辦了,例如上述使用 wheel 事件中,用鼠標拖動滾動條之所以能夠使用 scroll 事件,就是因為能夠很容易地確定當前主動滾動容器元素是哪一個。

所以,問題的關鍵在于,如何判斷出當前主動滾動的容器元素,只要解決了這個問題,剩下的就很好辦了。

不論是鼠標滾輪滾動還是鼠標按在滾動條上拖動滾動條滾動,都會觸發 scroll 事件,并且這個時候,在坐標系 Z 軸上,鼠標的坐標肯定是位于滾動容器元素所占的面積之內的,也就是說,在 Z 軸上,鼠標肯定是懸浮或者位于滾動容器元素之上。

鼠標在屏幕上移動的時候,是可以獲取到鼠標當前坐標的。

如何使用原生JS控制多個滾動條同步跟隨滾動效果

其中, clientXclientY 就是當前鼠標相對于視口的坐標,可以認為,只要這個坐標在某個滾動容器的范圍內,則認為這個容器元素就是主動滾動容器元素,容器元素的坐標范圍可以使用 getBoundingClientRect 進行獲取。

下面是鼠標移動到 .left 元素中的示例代碼:

if (e.clientX>l.left && e.clientX<l.right && e.clientY>l.top) {
  // 進入 .left元素中
}

這樣確實是可以的,不過考慮到兩個滾動容器元素幾乎占據了整個屏幕面積,所以 mousemove 所要監聽的面積未免有點大,對于性能可能要求較高,所以其實可以換成 mouseover 事件,只需要監聽鼠標有沒有進入到某個滾動容器元素即可,也省去上述的坐標判斷了。

addEventListener('mouseover',function(){
 // 進入 .left滾動容器元素內
})

當確定了鼠標主動滾動的容器元素是哪一個時,只需要處理這個容器的滾動事件,另外一個跟隨滾動容器的滾動事件不做處理即可。

如何使用原生JS控制多個滾動條同步跟隨滾動效果

嗯,效果很不錯,性能也很好, perfect ,可以收工嘍~

按比例滾動

上述示例全部是在兩個滾動容器元素的內容高度完全一致的情況下的效果,如果這兩個滾動容器元素的內容高度不同呢?

那就是下面這種效果:

如何使用原生JS控制多個滾動條同步跟隨滾動效果

可見,由于兩個滾動容器元素的內容高度不同,所以最大的 scrollTop 也就不同,就會出現當其中一個 scrollTop 值較小的元素滾到底時,另外一個元素還停留在一半,或者當其中一個 scrollTop 值較大的元素才滾到一半時,另外一個元素就已經滾到底了。

這種情況很常見,例如你用 markdown 寫作時,一個一級標題標記 # 在編輯模式下占用的高度,一般都是小于預覽模式占用的高度的,這樣就出現了左右兩側滾動高度不一致的情況。

所以,如果將這種情況也考慮進來的話,那么就不能簡單地為兩個滾動容器元素相互設置 scrollTop 值那么簡單。

雖然無法固定住滾動容器內容的高度,但是有一點可以確定,滾動條最大滾動高度,或者說 scrollTop 的值,肯定是與滾動容器內容的高度與滾動容器本身的高度呈一定的關系。

由于需要知道滾動容器內容的高度,還要存在滾動條,所以需要給此容器元素加個子元素,子元素高度不限,就是滾動容器內容的高度,容器高度固定,溢出滾動即可。

<div id="container">
 <div class="left">
	 <div class="child"></div>
 </div>
 <div class="right">
	 <div class="child"></div>
 </div>
</div>

結構示例如下:

如何使用原生JS控制多個滾動條同步跟隨滾動效果

通過我的觀察推論與實踐驗證,已經確定下來了它們之間的關系,很簡單,就是最基本的加減法運算:

滾動條的最大滾動高度(scrollTopMax) = 滾動容器內容的高度(即子元素高度ch) - 滾動容器本身的高度(即容器元素高度ph)

如何使用原生JS控制多個滾動條同步跟隨滾動效果

也就是說,如果已經確定了滾動容器內容的高度(即子元素高度ch)與滾動容器本身的高度(即容器元素高度ph),那么就一定能確定滾動條的最大滾動高度( scrollTop ),而這兩個高度值基本上都是可以獲取到的,所以就能得到 scrollTop

因此,想要讓兩個滾動元素容器等比例上下滾動,即其中一個元素滾到頭或者滾到底,另外一個元素也能對應滾到頭和滾到底,那么只要得到這兩個滾動容器元素之間的 scrollTop 最大值的比例( scale )就行了。

如何使用原生JS控制多個滾動條同步跟隨滾動效果

確定了 scale 之后,實時滾動時,只需要獲取主動滾動容器元素的 scrollTop1 ,就能得到另外一個跟隨滾動的容器元素對應的 scrollTop2

如何使用原生JS控制多個滾動條同步跟隨滾動效果

思路弄清晰了,寫代碼就是很容易的事情了,效果如下:

如何使用原生JS控制多個滾動條同步跟隨滾動效果

關于“如何使用原生JS控制多個滾動條同步跟隨滾動效果”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

js
AI

通化县| 上犹县| 淳化县| 农安县| 资中县| 青神县| 民权县| 古田县| 乐陵市| 准格尔旗| 图木舒克市| 临泉县| 威宁| 长垣县| 英超| 岳阳市| 山丹县| 宜都市| 大洼县| 小金县| 恭城| 观塘区| 晋城| 门头沟区| 莱芜市| 治县。| 宜州市| 宿迁市| 改则县| 舟山市| 军事| 贵州省| 松潘县| 马关县| 南岸区| 冀州市| 额济纳旗| 尚义县| 新丰县| 龙井市| 木兰县|