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

所属分类: HTML/Xhtml / 网页制作 阅读数: 595
收藏 0 赞 0 分享

不知道大家有没有遇到过这样的需求,在某个 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滚动条控制的详细总结和讲解,以及一些基本使用方法。

到此这篇关于html中dom元素滚动条滚动控制小结详解的文章就介绍到这了,更多相关dom元素滚动条滚动内容请搜索脚本之家以前的文章或继续浏览下面的相关文章,希望大家以后多多支持脚本之家!

更多精彩内容其他人还在看

用标准dl,dt,dd标签抛弃table列表

现在,越来越多的前端开发er们开始使用xHTML+CSS替代最初的table布局完成网页的整体布局,不但让网站降低了开发和维护的成本,而且代码也更语义化了。但是,并不是说table从此消失了,它仍然被很多人用来作为网页中数据表现的必需品,比如个人信息数据列表等。事实上,使用HTM... 查看详情
收藏 0 赞 0 分享

HTML网页中的URL表示方式

在HTML中,常见的URL有多种表示方式: 相对URL: 复制代码代码如下: example.php demo/example.php ./example.php ../../example.php /example.php 绝对URL: 复制代码代码如下: http://jb5... 查看详情
收藏 0 赞 0 分享

Web页面 自定义选择框Select

select下拉列表表单可能大家都很熟悉,不过默认的下拉列表表单往往会让一些网站觉得丑陋,同时用CSS也很难调整select的样式。因此许多网站位了做出更符合网站风格的select下拉表单,往往会用JS来模拟这种效果。比如我们很熟悉的土豆网,淘宝商城和亚马逊都是用JS做的下拉列表... 查看详情
收藏 0 赞 0 分享

html 标签ID可以是变量

<table id=" <%=var1%>">,调用的时候必须用var1的实际值了 JS里面也是一样 document.getElementById(" <? echo $blogid; ?>"); 具体... 查看详情
收藏 0 赞 0 分享

iframe 自适应大小实现代码

页面域关系: 主页面a.html所属域A:www.jb51.net 被iframe的页面b.html所属域B:www.jb51.cn,假设地址:http://www.jb51.cn/b.html 实现效果: A域名下的页面a.html中通过iframe嵌入B域名下的页面b.htm... 查看详情
收藏 0 赞 0 分享

40多个漂亮的网页表单设计实例

网页表单是访问者与网站拥有者主要的沟通途径。返馈总是重要的,这就是我们为什么确保网页表单容易理解和使用起来比较直观的原因,尽管如此,甚至在形式设计中它也担当创意中的有效部分。网页表单并非都是乏味的,使用css或flash,你能确保它们具有吸引力且有效。要注意,你需要提出一些独特且... 查看详情
收藏 0 赞 0 分享

HTML减肥 精简HTML标记制作网页

HTML 4HTML (非XHTML),MIME type 为 text/html ,允许省略一些标签。通过 HTML 4 DTD,你可以省略以下标签(那些所谓可避免的元素,这里用删除线加以标记)</area></base><body><... 查看详情
收藏 0 赞 0 分享

HTML网页制作教程 谨慎使用iframe标记

使用 iframe 可以轻易的调用其他网站的页面,但应谨慎使用。它比创建其他 DOM 元素(包括 style 和 script)多耗费数十甚至数百倍的性能。增加100个不同元素的时间对比显示 iframe 是多么耗费性能: 使用 iframe 的页面通常没有这么多 if... 查看详情
收藏 0 赞 0 分享

HTML 网页头部代码全清楚

以下所有代码全是在<head>...</head>之间,具体内容有:1,<title>…</title>标题元素,帮助用户更好识别文件,有且只有一个。当作为首页或收藏时做文件名。2,<link>&helli... 查看详情
收藏 0 赞 0 分享

HTML 5 Reset Stylesheet

这份css reset是在Eric Meyers的 CSS reset基础上修改出来的,特别针对HTML5调整了相应标签的初始化样式。 /* html5doctor.com Reset Stylesheet v1.4 2009-07-27 Author: Richard Clar... 查看详情
收藏 0 赞 0 分享
查看更多