zoukankan      html  css  js  c++  java
  • window.onscroll

    ---恢复内容开始---

    今天在学习javascript的过程中被onscroll这个东西堵了一下午.心情极度郁闷.

    在高度较大的网页中,我们通常会加一个返回顶部的按钮,方便用户操作.

    代码如下:

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <title></title>
            <style type="text/css">
                div{height:300px;}
                #btn1{position:fixed;bottom:0;right:0;}
            </style>
            <script type="text/javascript">
                window.onload = function(){
                    var oDiv = document.getElementsByTagName('div');
                    var oBtn = document.getElementById('btn1');
                    var timer = null;
                    var oSys = true;
                    var i = 0;
                    for (i = 0;i<oDiv.length;i++)
                    {
                        if(i%2 == 0)
                        {
                            oDiv[i].style.background = 'yellow';
                        }else if(i%3 == 0)
                        {
                            oDiv[i].style.background = 'red';
                        }else if(i%5 == 0)
                        {
                            oDiv[i].style.background = 'blue';
                        }else
                        {
                            oDiv[i].style.background = 'green';
                        }
                    }
                    window.onscroll = function(){
                        if(!oSys)
                        {
                            clearInterval(timer);
                        }
                        oSys = false;
                    }
                    oBtn.onclick = function(){
                        timer = setInterval(function(){
                            var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
                            var iSpeed = Math.floor(-scrollTop/8);
                            oSys = true;
                            if(!scrollTop)
                            clearInterval(timer);
                            document.documentElement.scrollTop = scrollTop + iSpeed ;
                        },300)
                    }
                }
            </script>
        </head>
        <body>
            <input type="button" id="btn1" value="backtotop" />
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
            <div></div>
        </body>
    </html>

    弄这么多DIV纯粹是为了填充高度,其实大可不必,设置一个高大上的DIV足以,但是当时脑残了.废话不说.实现的功能就是点击返回顶部按钮的时 候,页面可以以一个舒服的缓慢减速效果移动到顶部.这当中就产生了一个问题.如果页面很长,用户在点击返回顶部按钮后,页面移动到顶部的过程中想停下来 (也许发现了什么有趣的东西),如何去停止计时器.

    大家知道,在页面想顶部移动过程中,势必要触发window.scroll事件.如果要在触发事件后停下来的话,很简单:

    window.onscroll = function(){
         clearInterval(timer);          
    }

    这样,只要用户在页面返回顶部过程中拖动滑动条,页面就会停止自动滚动.但是很明显,返回顶部的函数也会触发window.onscroll事件,这样,我们点击返回顶部后,页面向上移动一下,就会停下来.因为计时器被清除了.

    那么如何才能让浏览器识别出到底是系统在执行函数的自动滚动,还是用户自己操作的呢?

    在第一段代码中,我们声明了一个变量:oSys,定义为true.之后我们在计时器函数中插入了它(请自己看代码).这样每次计时器执行内置函数的时候,都会初始化oSys的值为true.

    结合下面的代码段:

    window.onscroll = function(){
       oSys = false;
    }

    效果就是,当计时器中的函数在执行过程中,oSys变量的值被初始化为true.而一旦函数执行滚动语句,就触发window.onscroll事件,导致oSys的值变为false?为了检验这个结论,下了下面代码

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title></title>
        </head>
        <body>
            <div style="height:5000px;100%;background:gray;"></div>
            <input type="button" id="btn1" value="toTop" style="position:fixed;bottom:0;right:0;"/>
            <script type="text/javascript">
                var oSys = true;
                var oBtn = document.getElementById('btn1');
                oBtn.onclick = function(){
                    setInterval(function(){
                        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
                        var iSpeed = Math.floor(-scrollTop/8);
                        var oSys = true;
                        if(scrollTop){
                            document.documentElement.scrollTop = document.body.scrollTop = scrollTop + iSpeed;
                            alert(oSys);
                        }
                    },3000)
                window.onscroll = function(){
                    oSys = false;
                }
                }
            </script>
        </body>
    </html>

    结果发现每次弹出的都是true.这说明我们上面的推论是错误的.

    那就是说window.onscroll事件是在滚动完成后触发的,而不是滚动的同时.这也符合函数按顺序依次执行的逻辑:在滚动函数执行完成后, 进入window.onscroll触发的函数.那么可以确定,每次进入window.onscroll函数时,oSys的值总是true.而触发 onscroll事件后,进入onscroll引用的函数function(){oSys = false},然后oSys的值变为false.

    假设我们加上这样一段代码

    window.onscroll = function(){
        if(!oSys)
        {
            clearInterval(timer);   
        }  
        oSys = false;  
    }

    当计时器函数的一个周期执行完毕后,并且触发的onscroll事件函数也执行完毕后,oSys的值一定为false.此时如果又进入了onscroll事件函数,那么有两种可能.

    1.计时器函数进入了下一次循环,初始化oSys的值为true.执行完自身后,触发onscroll事件,进入onscroll触发的匿名函数,此事,oSys的值为true.跳过if语句,不清除计时器.

    2.计时器还没有进入下一次循环,是用户手动操作触发了onscroll事件的函数,那么此时oSys的值由于没有进过计时器函数内部的oSys初始化,所以值仍然为false.所以会进入if语句,清除计时器.

  • 相关阅读:
    <Redis开发与运维> 阅读笔记
    请求行,请求头,请求体详解
    char 与 varchar 的区别
    python字符串的常用方法。
    快速排序的代码及原理
    C#之Dictionary源码
    C#中构造函数
    U3D——单例模式的用法
    U3D学习——设置VS2019作为开发工具
    U3D学习——脚本运行周期
  • 原文地址:https://www.cnblogs.com/zhangxiaolei521/p/5022416.html
Copyright © 2011-2022 走看看