javascript - 当选项卡处于非事件状态时,如何使进度条的 setInterval 起作用

标签 javascript jquery html

我可以看到这里提出了几个类似的问题,但不幸的是我找不到我期望的答案。 我对编程很陌生,正在尝试 Javascript 进度条。每当进度条超出宽度时,我都会有一个倒计时计数器,但我遇到了问题,当焦点选项卡处于非事件状态时,进度条会暂停,从而使计数器不倒计时。 我想到了使用网络 worker http://www.tutorialspoint.com/html5/html5_web_workers.htm但我无法让它发挥作用。我将不胜感激来到这里的任何形式的帮助。 下面是我的代码。

<!DOCTYPE html>
<html>
    <head>
        <script 
           src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/
           jquery.min.js">
       </script>
    <style>
        #progressContainer {
            position: relative;
            width: 97%;
            height: 25px;
            background-color: #ddd;
            margin-bottom: 15px;
        }
        #progressBar {
            position: absolute;
            width: 0%;
            height: 100%;
            background-color: #A9A9A9;
        }
        #container{
            width: 200px;
            height: 200px;
            border: 1px solid black;
            padding: 10px
        }
    </style>

    <script>
        $(document).ready(function(){
            $("#countDownBtn").click(function(){

                var cdNumber = $("#countDownId").val();
                var id = setInterval(frame, 100);
                var elem = document.getElementById("progressBar");
                var progressBarWidth = 101;

                function frame() {                 

                    if (progressBarWidth === 0) {
                        clearInterval(id);
                        cdNumber--;                     
                        $("#countDownId").val(cdNumber);
                        console.log(cdNumber);

                        if (cdNumber === 0) {
                            clearInterval(id);          
                        }
                        else {
                            elem.style.width = '100%';
                            progressBarWidth = 100;
                            //alert("Hi");
                        }   
                    } 
                    else {
                        progressBarWidth--;
                        elem.style.width = progressBarWidth + '%';
                    }         
                }                    
            });
        });
    </script>

   </head>
   <body>
    <div id="container">
        <div>
            <input type="text" id="countDownId" value="">
            <button id="countDownBtn" class="btn">Click</button>
        </div><br>
        <div id="progressContainer">
        <div id="progressBar"></div>
        </div>
    </div>
  </body>

最佳答案

当依赖某个区间的精度时,你总会遇到这样的问题;甚至requestAnimationFrame。它们并不精确。

更好的方法(不仅在这种情况下,而且几乎每次你都必须随着时间的推移转换一个值)是保存 startTime 并计算间隔中耗时(如 @ Nosyara 已经建议过)。

当处理缩放因子和/或暂停这些东西时,事情可能会再次变得困惑。这是用于此任务的实用程序:

// The basic concept of this "Clock" is a linear equation over Date.now()
// plus the logic to make this equation pausable.
// therefore it's completely independant of **any** interval; it's just math.
function Clock(v){
    var p=true,m=1,b=+v||0,n=Clock.now;
    return Object.assign(Object.create(Clock.prototype),{
        // getter() / setter(value)
        // I don't use real getter and setter, because this syntax 
        // allows/implements method-chaining
        value(v){return arguments.length?(b=(+v||0)-(!p&&m*n()),this):b+(!p&&m*n())},
        speed(v){return arguments.length?(v=+v||0,p||v===m||(b+=n()*(m-v)),m=v,this):m},
        paused(v){return arguments.length?(((v=!!v)===p)||(b+=n()*((p=v)?m:-m)),this):p},
    });
}
Object.assign(Clock.prototype,{
    valueOf(){return this.value()},
    //aliases for setting the paused() state; doesn't matter if you call them repeatedly.
    start(){return this.paused(false)},
    stop(){return this.paused(true)},
});
Clock.now=Date.now; //the function used for timing
//Clock.now=performance&&performance.now?performance.now.bind(performance):Date.now;

现在看你的代码:

$(function(){
    function frame(){
        //yes, countDown get's converted to Number
        var value = Math.max(0, countDown);
        var count = Math.ceil(value);
        var progress = value % 1;

        $progressBar.width( progress * 100 + "%" );

        //so that I don't update $countDown.val() on every frame, but only if necessary
        //on the other hand, it wouldn't be that bad.
        if(count !== lastCount) $countDown.val( lastCount = count );

        //either stop the countDown or request the next frame.
        if(value > 0) requestAnimationFrame(frame);
        else countDown.stop();
    }

    //create a Clock and set speed. Clock is paused by default.
    var countDown = Clock().speed( -1 / 10000/*ms*/ );

    var $progressBar = $("#progressBar");
    var $countDown = $("#countDownId");
    var lastCount;

    $("#countDownBtn").click(function(){
        //if !countDown.paused() then there already is a pending `requestAnimationFrame(frame)`
        //from the last call of frame()
        if(countDown.paused()) requestAnimationFrame(frame);

        countDown.value( $countDown.val() ).start();
    });
})

关于javascript - 当选项卡处于非事件状态时,如何使进度条的 setInterval 起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38361954/

相关文章:

javascript - IE 中的 float 问题

javascript - 关联数组并使用父级 d 作为 Selection.data() 的源数组

jquery - MVC 3.0 JQUERY 部分页面更新

html - Jquery 移动页面 ListView 内容未更新

javascript - 如何在同一 Controller 之间共享范围两次

javascript - 获取网站访问者的语言环境(语言)?

javascript - 删除 html 换行代码并仅在行包含某些内容时保留内容?

javascript - 滚动后将导航栏返回到原始位置

javascript - jquery在div中滑动一个元素

jquery - 如何删除注销按钮或链接上的启动画面?