html中dom元素滚动条滚动控制小结详解

ID:16251 / 打印

不知道大家有没有遇到过这样的需求,在某个 dom 元素中添加新的子元素,然后要求如果新添加的新元素超出容器的范围,那么我们需要自动滚动到新添加的子元素的位置,如下图所示效果:

那么接下来我们一边学习一些 dom 元素滚动相关的知识点,一边实现一个上图的效果和一些其他滚动相关的功能。

需要了解的dom属性和方法 scrollTop、clientHeight和scrollHeight

scrollTop 属性是一个描述容器元素内容的top值与容器元素( viewport )视口顶部 top 值之间的差值,即容器中内容向上滑动后超出容器视口的部分。可以通过修改此属性控制滚动状态。

clientHeight 是描述容器高度的 dom 属性。

scrollHeight 是描述容器内容高度的 dom 属性。

三个属性的关系如下图所示:

getBoundingClientRect()

此方法用来获取元素布局所需的一些几何属性,比如 leftrighttopbottomheightwidth 等。

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 的值越大,滚动条相对于原始状态( 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()实现

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()实现

基础实现

我们同样可以使用 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滚动条控制的详细总结和讲解,以及一些基本使用方法。

上一篇: 如何为 Element UI 里的 autosize textarea 设置高度
下一篇: html post请求之a标签的两种用法解析

作者:admin @ 24资源网   2024-11-04

本站所有软件、源码、文章均有网友提供,如有侵权联系308410122@qq.com

与本文相关文章

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。