• jacascript 滚动 scroll 与回到顶部


    前言:这是笔者学习之后自己的理解与整理。如果有错误或者疑问的地方,请大家指正,我会持续更新!

    滚动 scroll

      scrollHeight 表示元素的总高度,包括由于溢出而无法展示在网页的不可见部分

      scrollWidth 表示元素的总宽度,包括由于溢出而无法展示在网页的不可见部分

      没有滚动条时,scroll 和 client 属性的结果相等,即 scrollWidth= padding + width; scrollHeight= padding + height;

      存在滚动条时,但元素设置宽高大于等于元素内容宽高时(没有内容溢出),scroll 和 client 属性的结果相等,滚动条是有宽度的

      存在滚动条,但元素设置宽高小于元素内容宽高(存在内容溢出),scroll 属性大于 client 属性;

      scrollHeight 属性存在兼容性问题,chrome 和 safari 浏览器中,scrollHeight 包含 padding-bottom;而 IE 和 firefox 不包含 padding-bottom;

            <style type="text/css">
                *{padding: 0;margin: 0;}
                #noScroll{
                    width: 100px;
                    height: 100px;
                    padding: 10px;
                    margin: 10px;
                    border: 1px solid black;
                }
                #noOverScroll{
                    width: 100px;
                    height: 100px;
                    padding: 10px;
                    margin: 10px;
                    border: 1px solid black;
                    overflow:scroll;
                    font-size:20px;
                    line-height:1;
                }
                #overScroll{
                    width: 100px;
                    height: 100px;
                    padding: 10px;
                    margin: 10px;
                    border: 1px solid black;
                    overflow:scroll;
                    font-size:20px;
                    line-height:200px;
                }
            </style>
            
            <div id="noScroll"></div>
            <div id="noOverScroll">内容</div>
            <div id="overScroll">内容</div>        
            
            <script>
                var oNoScroll = document.getElementById('noScroll');
                //没有滚动条时,scrollHeight与clientHeight属性结果相等,scrollWidth与clientWidth属性结果相等
                console.log(oNoScroll.scrollHeight);//120
                console.log(oNoScroll.scrollWidth);//120
                console.log(oNoScroll.clientHeight);//120
                console.log(oNoScroll.clientWidth);//120
                
                var oNoOverScroll = document.getElementById('noOverScroll');
                //存在滚动条时,但元素设置宽高大于等于元素内容宽高时(没有内容溢出),scroll 和 client 属性的结果相等;
                //103(120-17)
                console.log(oNoOverScroll.scrollHeight);//120
                console.log(oNoOverScroll.scrollWidth);//120
                console.log(oNoOverScroll.clientHeight);//120
                console.log(oNoOverScroll.clientWidth);//120        
    
                var oOverScroll = document.getElementById('overScroll');
                //存在滚动条,但元素设置宽高小于元素内容宽高,即存在内容溢出的情况时,scroll属性大于client属性
                //scrollHeight 属性存在兼容性问题,chrome 和 safari 浏览器中,scrollHeight 包含 padding-bottom;而 IE 和 firefox 不包含 padding-bottom;
                //chrome/safari:220(200+10+10)
                //firefox/IE:210(200+10)
                console.log(oOverScroll.scrollHeight);//220
                //103(120-17)
                console.log(oOverScroll.scrollWidth);//103
                //103(120-17)
                console.log(oOverScroll.clientHeight);//103
                console.log(oOverScroll.clientWidth);//103    
            </script>

      scrollTop 属性表示隐藏在内容区域上方的像素数。元素未滚动时,scrollTop 的值为0,如果元素被垂直滚动了,scrollTop 的值大于0,且表示元素上方不可见内容的像素宽度;

      scrollLeft 属性表示隐藏在内容区域左侧的像素数。元素未滚动时,scrollLeft 的值为0,如果元素被水平滚动了,scrollLeft 的值大于0,且表示元素左侧不可见内容的像素宽度;

      当滚动条滚动到内容底部时,scrollHeight == scrollTop + clientHeight;

      可以通过控制 scrollTop、scrollLeft,控制滚动条;(第一种控制滚动条的方法

    <style type="text/css">
                #test{
                    width: 100px;
                    height: 100px;
                    padding: 10px;
                    margin: 10px;
                    border: 1px solid black;
                    overflow:scroll;
                    font-size:20px;
                    line-height:200px;
                }
            </style>
            <div id="test">内容</div>
            <button id='btnDown'>向下滚动</button>
            <button id='btnUp'>向上滚动</button>
            
            <script>
                var oTest = document.getElementById('test');
                var oBtnDown = document.getElementById('btnDown');
                var oBtnUp = document.getElementById('btnUp');
                oBtnDown.onclick = function(){
                    oTest.scrollTop += 10;
                }
                oBtnUp.onclick = function(){
                    oTest.scrollTop -= 10;
                }
            </script>

    页面尺寸

      document.documentElement.clientHeight 表示页面的可视区域的尺寸;

      document.documentElement.scrollHeight 表示 html 元素内容的实际尺寸;但是由于各个浏览器表现不一样,分为以下几种情况:

    1. html 元素没有滚动条时,IE 和 firefox 的 client 和 scroll 属性始终相同,且返回可视区的尺寸大小;而 chrome 和 safari 不一样,clientHeight 返回可视区域大小,而 scrollHeight 返回元素内容大小;
    2. html 元素存在滚动条时,各个浏览器都表现正常。clientHeight 返回可视区域大小,而 scrollHeight 返回元素内容大小;

      因此要取得文档实际高度时要取得 <html> 元素的 scrollHeight 和 clientHeight 的最大值

            <script type="text/javascript">
                var docHeight = Math.max(document.documentElement.scrollHeight,document.documentElement.clientHeight);
                var docWidth  = Math.max(document.documentElement.scrollWidth,document.documentElement.clientWidth);
            </script>

    页面滚动

      理论上,通过 document.documentElement.scrollTop 和 scrollLeft 可以反映和控制页面的滚动;但是 chrome 和 safari 浏览器是通过 document.body.scrollTop 和scrollLeft 来控制的;

      所以,页面的滚动高度兼容写法是

            <script type="text/javascript">
                var docScrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            </script>

      可以利用 scrollTop 来实现回到顶部的功能(第一种回到顶部的方法);

        <body style="height:1000px">
            <button id='btn' style="position:fixed">回到顶部</button>
            
            <script>
                var oBtn = document.getElementById('btn');
                function scrollTop(){
                    var docScrollTop = document.documentElement.scrollTop || document.body.scrollTop;
                    if(docScrollTop != 0){
                        document.body.scrollTop = document.documentElement.scrollTop = 0;
                    }
                }
                oBtn.onclick = scrollTop;
            </script>
        </body>

      还有两个 window 的只读属性可以获取整个页面滚动的像素值,它们是 pageXOffset 和 pageYOffset;IE8及以下浏览器不支持

      window.pageXOffset 表示水平方向上页面滚动的像素值;

      window.pageYOffset 表示垂直方向上页面滚动的像素值;

    滚动方法

    scrollTo(x,y)

      scrollTo(x,y) 方法滚动当前 window 中显示的文档,让文档中由坐标 x 和 y 指定的点位于显示区域的左上角;

      第二种回到顶部的方法

        <body style="height:1000px">
            <button id='btn' style="position:fixed">滚动</button>
            <script>
                var oBtn = document.getElementById('btn');
                oBtn.onclick = function(){
                    scrollTo(0,0);
                }
            </script>
        </body>

    scrollBy(x,y)

      scrollBy(x,y) 方法滚动当前 window 中显示的文档,x 和 y 指定滚动的相对量;

      第二种控制滚动条的方法

      只要把当前页面的滚动长度 document.body.scrollTop 作为参数,逆向滚动(把滚动长度设为 y,并且为负值),则可以实现第三种回到顶部的效果;

        <body style="height:1000px">
            <button id='btnDown' style="position:fixed">向下滚动</button>
            <button id='btnUp' style="position:fixed;top:40px">向上滚动</button>
            <script>
                var oBtnDown = document.getElementById('btnDown');
                var oBtnUp = document.getElementById('btnUp');
                oBtnDown.onclick = function(){
                    scrollBy(0,10);
                }
                oBtnUp.onclick = function(){
                    scrollBy(0,-10);
                }
            </script>
        </body>

    scrollIntoView()

      Element.scrollIntoView() 方法滚动当前元素,进入浏览器的可见区域;

      该方法可以接受一个布尔值作为参数。如果为true,表示元素的顶部与当前区域的可见部分的顶部对齐(前提是当前区域可滚动);如果为false,表示元素的底部与当前区域的可见部分的尾部对齐(前提是当前区域可滚动)。如果没有提供该参数,默认为true

      第四种回到顶部的方法

    <style type="text/css">
            *{padding: 0;margin: 0;}
            #test{
                height:100px;
                width:100px;
                position:absolute;
                left:0;
                top:200px;
                background-color:green;
            }
            #btnTop{
                position:fixed;
            }
            #btnBottom{
                position:fixed;
                top:40px;
            }
        </style>
        <body style="height:1000px">
            <div id="test"></div>
            <button id='btnTop'>滚动到页面开头</button>
            <button id='btnBottom'>滚动到页面结尾</button>
            
            <script>
                var oTest = document.getElementById('test');
                var oBtnTop = document.getElementById('btnTop');
                var oBtnBottom = document.getElementById('btnBottom');
                oBtnTop.onclick = function(){
                    oTest.scrollIntoView();
                };
                oBtnBottom.onclick = function(){
                    oTest.scrollIntoView(false);
                }
            </script>
        </body>

    scrollIntoViewIfNeeded(alignCenter)

      scrollIntoViewIfNeeded(alignCenter) 方法只在当前元素在视口中不可见的情况下,才滚动浏览器窗口或容器元素,最终让它可见。如果当前元素在视口中可见,这个方法什么也不做;该方法只有 chrome 和 safari 支持

      如果将可选的 alignCenter 参数设置为 true,则表示尽量将元素显示在视口中部(垂直方向);尽量的意思是可能不成功,比如有元素有一半显示,一半隐藏,那么只会全部显示,但不会显示在视口中部;

    <style type="text/css">
            #test{
                height:100px;
                width:100px;
                /*position:absolute;
                left:0;
                top:500px;*/
                background-color:green;
            }
            #btn{
                position:fixed;
                top: 0;
            }
        </style>
        <body>
            <ul>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
            </ul>
            <div id="test"></div>
            <ul>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
                <li></li>
            </ul>
            <button id='btn'>滚动到页面中间</button>
            <script>
                var oTest = document.getElementById('test');
                var oBtn = document.getElementById('btn');
                
                oBtn.onclick = function(){
                    oTest.scrollIntoViewIfNeeded();
                };
            </script>
        </body>

    scrollByLines(lineCount)

      scrollByLines(lineCount) 方法将元素的内容滚动指定的行髙,lineCount 值可以是正值, 也可以是负值,该方法只有 safari 支持

    scrollByPages(pageCount)

      scrollByPages(pageCount) 方法将元素的内容滚动指定的页面高度,具体高度由元素的高度决定;该方法只有safari支持

    回到顶部

      前文有很多种方法可以实现回到顶部功能,有时候需要为回到顶部增加动画效果,滚动条以一定的速度回滚到顶部;

      动画有两种:一种是CSS动画,需要有样式变化配合 transition;一种是 javascript 动画,使用定时器来实现;  

      在前文的实现中,scrollTop、scrollTo() 和 scrollBy() 方法可以增加动画,且由于无样式变化,只能增加javascript动画;

      定时器又有 setInterval、setTimeout 和 requestAnimationFrame 这三种可以使用,下面使用性能最好的定时器 requestAnimationFrame 来实现;

      IE9及以下浏览器不支持该方法,可以使用 setTimeout 来兼容;

      由于 scrollTop、scrollBy() 和 scrollTo()方法,都以 scrollTop 值是否减少为0作为动画停止的参照,且三个动画的原理和实现都基本相似,性能也相似。最终,以最常用的scrollTop属性实现动画增强效果;

      当然,如果觉得50的速度不合适,可以根据实际情况进行调整;

        <style>
            *{padding: 0;margin: 0;}
            .goTop{
                position:fixed;
                right:10px;
                bottom: 10px;
                height:50px;
                width: 50px;    
                text-align:center;
                background-color: lightblue;
                border-radius: 20%;
                overflow: hidden;
            }
            .goTop:hover:before{
                top:50%;
            }
            .goTop:hover .directTop{
                visibility: hidden;
            }
            .goTop:before{
                position: absolute;
                top: -50%;
                left: 50%;
                transform: translate(-50%,-50%);
                content:'回到顶部';
                width: 40px;
                color:peru;
                font-weight:bold;
            }    
            .directTop{
                visibility: visible;
                display:inline-block;
                margin-top: 20px;
                height:20px;
                width: 20px;
                border: 3px solid;
                border-color: white transparent transparent white;
                transform:rotate(45deg);
            }
        </style>
    
        <body style="height:2000px;">
            <div class="goTop">
                <div class="directTop"></div>
            </div>    
            <script>
                var timer  = null;
                var oGoTop = document.getElementsByClassName('goTop')[0];
                oGoTop.onclick = function(){
                    cancelAnimationFrame(timer);
                    timer = requestAnimationFrame(function fn(){
                        var oTop = document.body.scrollTop || document.documentElement.scrollTop;
                        if(oTop > 0){
                            document.body.scrollTop = document.documentElement.scrollTop = oTop - 50;
                            timer = requestAnimationFrame(fn);
                        }else{
                            cancelAnimationFrame(timer);
                        }    
                    });
                }
            </script>
            
            <!--setTimeout 兼容写法-->
            <!--<script>
                var timer  = null;
                var oGoTop = document.getElementsByClassName('goTop')[0];
                oGoTop.onclick = function(){
                    clearTimeout(timer);
                    timer = setTimeout(function fn(){
                        var oTop = document.body.scrollTop || document.documentElement.scrollTop;
                        if(oTop > 0){
                            document.body.scrollTop = document.documentElement.scrollTop = oTop - 50;
                            timer = setTimeout(fn,0);
                        }else{
                            clearTimeout(timer);
                        } 
                    },0);    
                }
            </script>-->
        </body>

       

    滚动事件

      scroll 事件是在 window 对象上发生的,它表示的是页面中相应元素的变化。当然,scroll 事件也可以用在有滚动条的元素上;

        <body style="height:1000px">
            <div id="result" style="position:fixed;top:10px;"></div>
            <script>
                var oResult = document.getElementById('result');
                window.onscroll = function(){
                    var docScrollTop = document.documentElement.scrollTop || document.body.scrollTop;
                    result.innerHTML = '页面的scrollTop:' + docScrollTop;
                }
            </script>    
        </body>

       有时候需要判断滚动方向

        <script type="text/javascript">
            function scroll( fn ) {
                var beforeScrollTop = document.documentElement.scrollTop || document.body.scrollTop,
                    fn = fn || function() {};
                window.addEventListener("scroll", function() {
                    var afterScrollTop = document.documentElement.scrollTop || document.body.scrollTop,
                        delta = afterScrollTop - beforeScrollTop;
                    if( delta === 0 ) return false;
                    fn( delta > 0 ? "down" : "up" );
                    beforeScrollTop = afterScrollTop;
                }, false);
            }
            scroll(function(direction) { 
                if(direction == 'down'){
                    console.log('向下');
                }else if(direction == 'up'){
                    console.log('向上');
                }
            });
        </script>

      JQuery判断滚动方向,

        <script type="text/javascript">
            function scroll( fn ) {
                var $window = $(window),
                    beforeScrollTop = $window.scrollTop(),
                    fn = fn || function() {};
            
                $window.scroll(function() {
                    var afterScrollTop = $window.scrollTop(),
                        delta = afterScrollTop - beforeScrollTop;
                    if( delta === 0 ) return false;
                    fn( delta > 0 ? "down" : "up" );
                    beforeScrollTop = afterScrollTop;
                });
            }
            scroll(function(direction) { 
                if(direction == 'down'){
                    console.log('向下');
                }else if(direction == 'up'){
                    console.log('向上');
                }
            });
        </script>

      还有一种方法,

           <script>  
                var scrollFunc = function (e) {  
                    var direct = 0;  
                    e = e || window.event;
                    //滚轮事件中有一个 wheelDelta 属性,当用户向前滚动鼠标滚轮时,wheelDelta 是120的倍数;当用户向后滚动鼠标滚轮时,wheelDelta 是 -120 的倍数;
                    //firefox 浏览器有关鼠标滚轮的信息则保存在 detail 属性中。当向前滚动鼠标滚轮时,这个属性的值是 -3 的倍数;当向后滚动鼠标滚轮时,这个属性的值是 3 的倍数。
                    if (e.wheelDelta > 0 || e.detail < 0) {   
                        console.log("滑轮向上滚动");  
                    }  
                    if (e.wheelDelta < 0 || e.detail > 0) { 
                        console.log("滑轮向下滚动");  
                    }  
                } 
                //firefox 浏览器不支持 mousewheel 事件,它支持 DOMMouseScroll 事件(该事件仅支持DOM2级事件处理程序的写法)
                if (document.addEventListener) {  
                    document.addEventListener('DOMMouseScroll', scrollFunc, false);  
                }  
                //滚动滑轮触发scrollFunc方法  
                window.onmousewheel = document.onmousewheel = scrollFunc;    
            </script>
  • 相关阅读:
    Go
    Go
    Go -11 Go 框架beego的简单 create run
    文本处理工具之:grep sed awk
    Linux系统布置java项目
    docker 启动mysql 本地连接
    time
    多行查询数据合并成一行进行展示
    settings的使用
    xlsxwriter
  • 原文地址:https://www.cnblogs.com/sspeng/p/6765612.html
Copyright © 2020-2023  润新知