不知道大家有沒有遇到過這樣的需求,在某個dom元素中添加新的子元素,然後要求如果新添加的新元素超出容器的範圍,那麼我們需要自動滾動到新添加的子元素的位置,如下圖所示效果:
那麼接下來我們一邊學習一些dom元素滾動相關的知識點,一邊實現一個上圖的效果和一些其他滾動相關的功能。
需要了解的dom屬性和方法scrollTop、clientHeight和scrollHeight
scrollTop屬性是一個描述容器元素內容的top值與容器元素( viewport )視口頂部top值之間的差值,即容器中內容向上滑動後超出容器視口的部分。可以通過修改此屬性控制滾動狀態。
clientHeight是描述容器高度的dom屬性。
scrollHeight是描述容器內容高度的dom屬性。
三個屬性的關係如下圖所示:
getBoundingClientRect()
此方法用來獲取元素佈局所需的一些幾何屬性,比如left 、 right 、 top 、 bottom 、 height 、 width等。
srollBy(x,y)
dom容器的scrollTo方法可以用來直接控制滾動條滾動指定的距離。當需要滾動到指定元素時,使用此方法比較方便。
srollTo(x,y)
dom容器的scrollTo方法可以用來直接控制滾動條滾動到指定位置。在控制滾動條滾動到頂部或者底部的時候使用此方法比較方便。
實現滾動控制準備
我們先準備一個html
<!DOCTYPE html><html> <head> <title>滾動條設置詳解</title> <style> #scroll_container{ height: 500px; width: 500px; overflow-y: scroll; padding: 50px; box-sizing: border-box; } .scroll_item{ height: 200px; width: 500px; margin-top: 20px; background-color: aquamarine; display: flex; align-items: center; justify-content: center; } </style> </head> <body> <div id=scroll_container> <div id=scroll_container> <div id=item1 class=scroll_item> <span>1</span> </div> <div id=item2 class=scroll_item> <span>2</span> </div> <div id=item3 class=scroll_item> <span>3</span> </div> <div id=item4 class=scroll_item> <span>4</span> </div> <div id=item5 class=scroll_item> <span>5</span> </div> </div> <button onclick=addItem()>添加一個元素</button> </div> </body> <script> let container=document.getElementById(scroll_container); let index=5; //添加一個元素function addItem(){ index+=1; let item=`<div id=${'item'+index} class=scroll_item> <span>${index}</span> </div>`; container.innerHTML+=item; setTimeout(()=>{ scrollToIndex(); }) } </script></html>上面的代碼包含一個可滾動的區域,並可以為滾動區域添加元素,也可以滾動到指定的元素位置,大致效果如下圖。
基礎實現
之前已經說明過scrollTop的含義,我們可以通過修改容器元素scrollTop值來控制滾動條滾動。 scrollTop的值越大,滾動條相對於原始狀態( scrollTop為0時)的滾動距離越大。
了解了scrollTop的含義,我們就可以利用scrollTop來實現滾動條的控制,那麼我們先實現一個滾動到底部的實現,為上面的代碼添加一個scrollToBottom()的方法:
function scrollToBottom(){ let y=container.scrollHeight-container.clientHeight; container.scrollTop=y;}對應的如果想要實現滾動到頂部我們只需要設置scrollTop為0即可:
function scrollToTop(){ container.scrollTop=0;}結合getBoundingClientRect()方法我們也可以輕鬆實現滾動到指定元素,其中getBoundingClientRect().top表示子元素頂部距離父元素視口頂部的距離:
function scrollToElement(el){ container.scrollTop+=el.getBoundingClientRect().top;}添加動畫滾動到底部
但是上面代碼的滾動未免太生硬了,我們可以為它添加一下動畫效果,可以藉助setInterval()實現一下。分析一下實現動畫效果的過程,動畫的實現無外乎是把一個變量的變化在一定的時間內完成,因此我們首先需要知道兩個變量,變量( scrollTop )偏移量和變化所需時間,而偏移量就是scrollTop的最終值減去原始值,變化時長一般設置成可以修改的參數。了解了以上過程,我們先以滾動到底部為例:
//首先編寫一個scrollToBottom函數function scrollToBottom(el){ if(!el){ el=container; } //原始值let startTop=el.scrollTop; //最終值let endTop=el.scrollHeight-el.clientHeight; //生成一個動畫控制函數let scrollAnimationFn=doAnimation(startTop,endTop,300,el); //執行動畫,每10ms執行一次let interval=setInterval(()=>{ scrollAnimationFn(interval) },10) }/** * @description: 一個生成動畫控制函數的工廠函數(使用閉包) * @param { startValue:變量原始值endValue:變量最終值duration:動畫時長el:執行滾動動畫的元素} * @return: null */function doAnimation(startValue,endValue,duration,el){ //使用閉包保存變量dy和step(每次動畫滾動的距離) let dy=0; let step=(endValue-startValue)/(duration/10); //返回動畫控制函數return function(interval){ dy+=step; if(dy>=endValue-startValue){ clearInterval(interval); } el.scrollTop+=step; } }修改addItem函數添加滾動到底部動畫:
function addItem(){ index+=1; let item=`<div id=${'item'+index} class=scroll_item> <span>${index}</span> </div>`; container.innerHTML+=item; setTimeout(()=>{ // scrollToIndex(); scrollToBottom(container); }) }然後為html加入一個滾動到底部的按鈕:
<button onclick=scrollToBottom()>滾動到底部</button>
按照上面的方法也可以實現一個常用的帶動畫滾動到頂部:
//編寫一個scrollToTop函數function scrollToTop(el){ if(!el){ el=container; } //原始值let startTop=el.scrollTop; //最終值let endTop=0; //生成一個動畫控制函數let scrollAnimationFn=doAnimation(startTop,endTop,300,el); //執行動畫,每10ms執行一次let interval=setInterval(()=>{ scrollAnimationFn(interval) },10) }為了適配滾動到底部我們需要修改一下動畫停止的時機判斷,修改後的doAnimation()函數如下:
function doAnimation(startValue,endValue,duration,el){ //使用閉包保存變量dy和step(每次動畫滾動的距離) let dy=0; let step=(endValue-startValue)/(duration/10); return function(interval){ dy+=step; //這裡改成使用絕對值判斷if(Math.abs(dy)>=Math.abs(endValue-startValue)){ clearInterval(interval); } el.scrollTop+=step; } }最後我們再給html添加一個滾動到底部按鈕:
<button onclick=scrollToTop()>滾動到頂部</button>
實現效果如下圖:
首先為html元素添加所需的按鈕和輸入框:
<input type=number placeholder=請輸入要滾動到的元素index style=width: 200px;/><button onclick=scrollToElement()>滾動到指定元素</button>
添加一個滾動指定元素的動畫執行函數:
function scrollToElement(containerEl,el){ if(!containerEl){ //父元素containerEl=container; } if(!el){ //獲取到要滾動到的元素let input=document.getElementsByTagName('input')[0]; let id='item'+input.value; if(!input.value){ id='item'+index; } el=document.getElementById(id); } let startTop=containerEl.scrollTop; let endTop=startTop+el.getBoundingClientRect().top; let scrollAnimationFn=doAnimation(startTop,endTop,300,containerEl); let interval=setInterval(()=>{ scrollAnimationFn(interval) },10)}實現效果如下:
scrollTo(x,y)的使用方法與scrollTop屬性的使用方法基本一致,父元素的scrollTo()方法可以控制滾動條滾動到指定位置,實際上相當於設置scrollTop的值。舉個例子說明一下:
//這里以y軸滾動為例element.scrollTo(0,y);element.scrollTop=y;//上面兩句的效果相同。
所以,使用scrollTo()方法控制滾動條與使用scrollTop基本一致,我們只需要簡單修改doAnimation()函數,代碼如下:
function doAnimation(startValue,endValue,duration,el){ //使用閉包保存變量dy和step(每次動畫滾動的距離) let dy=0; let step=(endValue-startValue)/(duration/10); return function(interval){ dy+=step; if(Math.abs(dy)>=Math.abs(endValue-startValue)){ clearInterval(interval); } //el.scrollTop+=step;//這行代碼修改為如下el.scrollTo(0,el.scrollTop+step); }}執行效果與使用scrollTop實現一致。
基礎實現
我們同樣可以使用scrollBy(x,y)實現對滾動條的控制,上面已經說明過, scrollBy()方法是控制滾動條滾動指定距離(注意不是位置)。使用scrollBy()可以很方便的實現滾動到指定元素的需求,代碼如下:
function scrollToElement(containerEl,el){ //因為getBoundingClientRect().top即為子元素頂部距離父元素頂部的距離,所以這個值就是子元素相對於父元素的偏移量,我們傳入這個值到scrollBy中,即滾動到指定元素containerEl.scrollBy(0,el.getBoundingClientRect().top);}滾動到底部:
function scrollToBottom(containerEl){ let dy=containerEl.scrollHeight-containerEl.clientHeight; containerEl.scrollBy(0,dy);}滾動到頂部
function scrollToTop(containerEl){ let dy=-(containerEl.scrollHeight-containerEl.clientHeight); containerEl.scrollBy(0,dy);}添加動畫
這裡我們修改一下動畫生成的函數,因為這裡我們scrollBy()的參數就是變量的偏移量,所以做出如下修改:
function scrollToBottom(containerEl){ if(!containerEl){ containerEl=container; } //dy即為偏移量let dy=containerEl.scrollHeight-containerEl.clientHeight; let scrollAnimationFn=doAnimation(dy,300,containerEl); let interval=setInterval(()=>{ scrollAnimationFn(interval) },10) } function scrollToTop(containerEl){ if(!containerEl){ containerEl=container; } //dy即為偏移量let dy=-(containerEl.scrollHeight-containerEl.clientHeight); let scrollAnimationFn=doAnimation(dy,300,containerEl); let interval=setInterval(()=>{ scrollAnimationFn(interval) },10) } function scrollToElement(containerEl,el){ if(!containerEl){ containerEl=container; } if(!el){ let input=document.getElementsByTagName('input')[0]; let id='item'+input.value; if(!input.value){ id='item'+index; } el=document.getElementById(id); } //dy即為偏移量let dy=el.getBoundingClientRect().top; let scrollAnimationFn=doAnimation(dy,300,containerEl); let interval=setInterval(()=>{ scrollAnimationFn(interval) },10) } /** * @description: * @param {type} * @return: */ function doAnimation(dy,duration,el){ //使用閉包保存變量exe_dy和step等變量(每次動畫滾動的距離) let exe_dy=0;//已經執行的偏移量let step=dy/(duration/10); return function(interval){ exe_dy+=step; if(Math.abs(exe_dy)>=Math.abs(dy)){ clearInterval(interval); } el.scrollBy(0,step); } }執行效果與使用scrollTop實現一致。
以上:point_up_2:就是自己對dom滾動條控制的詳細總結和講解,以及一些基本使用方法。
到此這篇關於html中dom元素滾動條滾動控制小結詳解的文章就介紹到這了,更多相關dom元素滾動條滾動內容請搜索武林網以前的文章或繼續瀏覽下面的相關文章,希望大家以後多多支持武林網!