Javascript 为什么在使用短间隔时更改CSS宽度的行为会很奇怪?

Javascript 为什么在使用短间隔时更改CSS宽度的行为会很奇怪?,javascript,jquery,html,css,Javascript,Jquery,Html,Css,这个想法是要有一个进度条,在20秒内从0%加载到100%,然后从0开始重新加载。为了实现这一点,我将setInterval与jQuery.css('width','+=0.1%)结合使用 一个间隔计为20秒,另一个间隔每20毫秒增加0.1%的div宽度。当第一个计时器启动时应该达到100%,对吗 但事实并非如此。首先,宽度没有按预期添加:它不是按0.1%的步长计算的,而是在逗号后面增加了更多的位置。第二,20秒在达到100%之前已经过去很久了。不同的浏览器在这里给出不同的结果。Chrome在重新

这个想法是要有一个进度条,在20秒内从0%加载到100%,然后从0开始重新加载。为了实现这一点,我将
setInterval
jQuery.css('width','+=0.1%)
结合使用

一个间隔计为20秒,另一个间隔每20毫秒增加0.1%的div宽度。当第一个计时器启动时应该达到100%,对吗

但事实并非如此。首先,宽度没有按预期添加:它不是按0.1%的步长计算的,而是在逗号后面增加了更多的位置。第二,20秒在达到100%之前已经过去很久了。不同的浏览器在这里给出不同的结果。Chrome在重新开始之前已经接近100%,Firefox在我的站点上达到70%时,20秒就结束了

即使使用1%的步数而不是0.1%的步数,它仍然不能正确相加,我仍然会在逗号后面找到位置,尽管不应该有任何位置

示例代码:

var区间;
$('.progressbar').css('width','0%');
间隔=设置间隔(函数(){
$('.progressbar').css('width','+=0.1%);
}, 20);
设置间隔(惊人负载,20000);
函数惊人加载(){
间隔时间;
$('.progressbar').css('width','0%');
间隔=设置间隔(函数(){
$('.progressbar').css('width','+=0.1%);
}, 20);
}
.progressbar{
高度:10px;
背景#0060ff;
边界半径:20px;
}

  • 跟踪经过的时间,而不是设置计时器以提高精度
  • 使用CSS3动画减少浏览器之间的计时器差异

  • 这可能是有用的

    为什么它的行为怪异?因为计时器不准确,您要将现有宽度增加0.1%,而不是将百分比增加0.1%(0.1+0.1%=0.1001%,等等)

    您的代码应该看起来更像这样

    $('.progressbar').css('width','0%”);
    setTimeout(函数startLoading(){
    变量宽度=$('.progressbar').prop('style').width;
    var newWidth=parseFloat(宽度)+0.1;
    如果(新宽度<100){
    $('.progressbar').css('width',newWidth+'%');
    }否则{
    $('.progressbar').css('width','0%');
    }
    设置超时(惊人加载,20);
    }, 20);
    
    .progressbar{
    高度:10px;
    背景#0060ff;
    边界半径:20px;
    }

    我不知道你为什么要用两个计时器来知道加载何时完成。 只需检查进度是否达到100,然后调用回调

    函数加载条(){
    var self=this;//我使用ES类,但您似乎更喜欢老式的方式。
    this.element=$('.progressbar');
    这个进度=0;
    此值为0.1,步长=0.1;
    这个时间间隔;
    this.start=函数(){
    console.log(“加载”);
    self.progress=0;
    if(自我进程间隔){
    clearInterval(self.progressInterval);
    }
    self.progressInterval=setInterval(self.updateProgress,10);
    }
    this.updateProgress=函数(){
    self.progress+=self.stepSize;
    //四舍五入
    self.progress=Math.round(self.progress*10)/10;
    css('width',self.progress+'%');
    如果(self.progress>=100){
    clearInterval(self.progressInterval);
    self.onComplete();
    }
    }
    this.onComplete=函数(){
    console.log('completed');
    //重新开始
    self.start();
    }
    }
    var loadingBar=新的loadingBar();
    loadingBar.start()
    
    .progressbar{
    高度:10px;
    背景#0060ff;
    边界半径:20px;
    }

    使用css动画或jquery
    .animate()

    您只需将持续时间设置为
    20000
    ,一切正常。如果必须在某个点停止,只需在animate回调中的
    progressBarLoop
    函数周围添加一个条件。(我将持续时间设置为5000,这样我们就不必等待20秒来重新启动)

    var-stop=false;
    函数progressBarLoop(){
    $('.progressbar').css('width','0%');
    $('.progressbar')。设置动画({
    宽度:'100%'
    },5000,'线性',函数(){
    如果(!停止){
    progressBarLoop();
    }
    });
    }
    progressBarLoop()
    
    .progressbar{
    高度:10px;
    背景#0060ff;
    边界半径:20px;
    }

    计时器不是超精确的。根据经验,根据许多因素,低于50毫秒的间隔触发频率可能比预期的低100%(即每100毫秒一次)。如果你想让进度在20秒内完成,那么计算每个刻度的实际百分比会使它看起来更准确

    var defaultDuration=20000//把这个换成什么都行
    函数加载栏(持续时间){
    var区间;
    var startTime=new Date().getTime();
    var endTime=开始时间+持续时间;
    $('.progressbar').css('width','0%');
    interval=setInterval(函数(){
    var pc=(new Date().getTime()-startTime)/(endTime startTime);
    $('.progressbar').css('width',(pc*100)+'%');
    }, 20);
    返回间隔;
    }
    var int=加载条(默认持续时间);
    setInterval(函数(){
    清除间隔(int);
    int=加载条(默认持续时间);
    },违约期限)
    
    .progressbar{
    高度:10px;
    背景#0060ff;
    边界半径:20px;
    }
    
    
    计时器不是超精确的。您最好跟踪实际经过的时间,并在此基础上将宽度设置为一个显式百分比。@Pointy我该怎么做?这个想法是为了得到一个简单的平滑进度条。最让我恼火的是Firefox和Chrome无法以0.1%的步长计算,而一个Internet Explorer却能令人惊讶地以0.1%的步长计算。“它没有以0.1%的步长计算,但逗号后面的位置要多得多”——这可能是由于浮点数固有的不精确性。“在2中加载的进度条