Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/473.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 进度条';即使我';我尝试了很多方法来强制重新油漆_Javascript_Jquery_Html_Css_Repaint - Fatal编程技术网

Javascript 进度条';即使我';我尝试了很多方法来强制重新油漆

Javascript 进度条';即使我';我尝试了很多方法来强制重新油漆,javascript,jquery,html,css,repaint,Javascript,Jquery,Html,Css,Repaint,我有一个JavaScript方法,它可以迭代大约200个输入,插入值,并触发onchange事件。这在Chrome和IE中分别需要2000毫秒和10000毫秒 我想制作一个进度条来显示进度 现在的问题是,浏览器在进程结束前不会重新绘制进度条,此时进度条将立即达到100% 在这里研究之后,我找到了三种方法并尝试了所有方法,但都不起作用: 以零或非零(例如200毫秒)超时在setTimeout中运行进度条更新 访问图元或相邻图元的“高度”属性,这将强制重新绘制 同时显示/隐藏元素并访问offset

我有一个JavaScript方法,它可以迭代大约200个输入,插入值,并触发onchange事件。这在Chrome和IE中分别需要2000毫秒和10000毫秒

我想制作一个进度条来显示进度

现在的问题是,浏览器在进程结束前不会重新绘制进度条,此时进度条将立即达到100%

在这里研究之后,我找到了三种方法并尝试了所有方法,但都不起作用:

  • 以零或非零(例如200毫秒)超时在setTimeout中运行进度条更新
  • 访问图元或相邻图元的“高度”属性,这将强制重新绘制
  • 同时显示/隐藏元素并访问offsetHeight属性
这是我的密码:

    <div class="cg-progress-bar">
        <div class="cg-progress-bar-completed">
            &nbsp;
        </div>
        <div class="cg-inline-block cg-progress-bar-force-repaint">
            &nbsp;
        </div>
    </div>

如何强制浏览器重新绘制

可能您的进程太重,正在崩溃执行线程。这意味着,在计算时,浏览器会稍微冻结,并且在处理计算时,可能无法与UI进行其他交互

为了避免这种情况,HTML5提供了web工作者技术。这是一种在浏览器环境中模拟多任务处理的方法,允许您执行繁重的任务,避免浏览器冻结

这里有一篇介绍这项技术的优秀文章,我已经成功地使用它创建了一个文件上传器,能够上传Gb长度的文件,并保持实时进度条:


我希望它能有所帮助。

好的,所以我以前的anwser没有像我希望的那样工作,所以这里有一个工作示例:

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>-</title>
    <style type="text/css" media="screen">
        div{
            margin: 0px;
            padding: 0px;
            height: 30px;
        }
        #wrapper{
            width: 300px;
            border: solid 1px black;
        }
        #progressBar{
            width: 0px;
            background-color: black;
            color: grey;
        }
    </style>
</head>
<body>
    <div id="wrapper"><div id="progressBar"></div></div>
    <script type="text/javascript">

        var progressBar = document.getElementById("progressBar")    
        var workerThread = new Worker('worker.js');

        function drawProgress(progress){
            var percentageComplete = Math.floor( (progress.current/progress.maximum)*100 ) + "%";
            progressBar.style.setProperty("width",percentageComplete)
        }

        workerThread.onmessage = function(e){
            drawProgress(e.data)
        }
    </script>
</body>
</html>

-
div{
边际:0px;
填充:0px;
高度:30px;
}
#包装纸{
宽度:300px;
边框:实心1px黑色;
}
#进度条{
宽度:0px;
背景色:黑色;
颜色:灰色;
}
var progressBar=document.getElementById(“progressBar”)
var workerThread=newworker('Worker.js');
功能进度(进度){
var percentageComplete=数学地板((当前进度/最大进度)*100)+“%”;
progressBar.style.setProperty(“宽度”,完成百分比)
}
workerThread.onmessage=函数(e){
提取进度(如数据)
}
worker.js

var sqlData = new Array( 236 );
var i = 0;
for ( let entry of sqlData ) {
    console.log( 'iteration of each' );
    postMessage( {
        current: i,
        maximum: sqlData.length
    } )
    for ( var n = 0; n < 200000; n++ ) {
        for ( let entry of sqlData ) {
            entry = Math.random()
        }
    }
    i++;
}
var-sqlData=新数组(236);
var i=0;
for(让输入sqlData){
log('each的迭代');
邮资({
当前:我,,
最大值:sqlData.length
} )
对于(变量n=0;n<200000;n++){
for(让输入sqlData){
entry=Math.random()
}
}
i++;
}

我认为这可能是最好的选择,因为没有黑客参与,这只是这种任务的方式。唯一的问题是很难在worker中获得JQuery。最好的方法是在主线程中完全检索SQL数据集,然后将其传输到工作线程中。

@K48补充说,它应该与IE9+兼容,因此下面是支持IE8+的解决方案:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>IE8 compatible</title>
    <style type="text/css">
        div{
            margin: 0px;
            padding: 0px;
            height: 30px;
        }
        #wrapper{
            width: 300px;
            border: solid 1px black;
        }
        #progressBar{
            width: 0px;
            background-color: black;
            color: grey;
        }
    </style>
</head>
<body>
    <div id="wrapper"><div id="progressBar"></div></div>
    <script type="text/javascript">
        var continueExecution = false;
        var progressBar = document.getElementById( "progressBar" );
        var i = 0;
        var sqlData = new Array( 236 );
        var lastDraw = (new Date).valueOf();

        function heavyloadFunction() {
            var entry = sqlData[ i ]

            // do something with the entry
            for ( var n = 0; n < 2000; n++ ) {
                for ( var h = 0; h < sqlData.length; h++ ) {
                    var cEntry = sqlData[h]
                    cEntry = Math.random()
                }
            }

            // finish entry work

            if(i < sqlData.length){
                i++;
                continueExecution = true;
            }else{
                console.log("finished")
                continueExecution = false;
            }
        }

        function drawProgress( progress ) {
            var percentageComplete = Math.floor( ( progress.current / progress.maximum ) * 100 ) + "%";
            progressBar.style.width = percentageComplete
        }

        function shouldReDraw(){
            var dNow = (new Date).valueOf();
            if(dNow - lastDraw > 16){
                // around 60fps
                lastDraw = dNow;
                return true;
            }else{
                return false;
            }
        }

        function excutionLoop() {
            heavyloadFunction();

            if ( continueExecution ) {
                if(shouldReDraw()){
                    drawProgress({
                        current: i,
                        maximum: sqlData.length
                    })

                    window.setTimeout( excutionLoop, 0 )
                }else{
                    excutionLoop()
                }
            }else{
                drawProgress({
                    current: i,
                    maximum: sqlData.length
                })
            }           
        }

        excutionLoop();
    </script>
</body>
</html>

IE8兼容
div{
边际:0px;
填充:0px;
高度:30px;
}
#包装纸{
宽度:300px;
边框:实心1px黑色;
}
#进度条{
宽度:0px;
背景色:黑色;
颜色:灰色;
}
var continueExecution=false;
var progressBar=document.getElementById(“progressBar”);
var i=0;
var sqlData=新数组(236);
var lastDraw=(新日期).valueOf();
函数heavyloadFunction(){
var entry=sqlData[i]
//对条目做些什么
对于(变量n=0;n<2000;n++){
for(var h=0;h16){
//60帧左右
lastDraw=dNow;
返回true;
}否则{
返回false;
}
}
函数exciutionloop(){
heavyloadFunction();
如果(继续执行){
if(shouldReDraw()){
牵引进度({
当前:我,,
最大值:sqlData.length
})
setTimeout(excutionLoop,0)
}否则{
exciutionloop()
}
}否则{
牵引进度({
当前:我,,
最大值:sqlData.length
})
}           
}
exciutionloop();
这个想法很简单,每次循环迭代都会中断执行,这样就可以进行重画


编辑:进行了一些改进,以防止绘图结果成为瓶颈。

只有在代码运行完成后,它才会在代码运行时重新绘制。看见顺便说一句,setTimeout方法应该是我发现的唯一查看
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>IE8 compatible</title>
    <style type="text/css">
        div{
            margin: 0px;
            padding: 0px;
            height: 30px;
        }
        #wrapper{
            width: 300px;
            border: solid 1px black;
        }
        #progressBar{
            width: 0px;
            background-color: black;
            color: grey;
        }
    </style>
</head>
<body>
    <div id="wrapper"><div id="progressBar"></div></div>
    <script type="text/javascript">
        var continueExecution = false;
        var progressBar = document.getElementById( "progressBar" );
        var i = 0;
        var sqlData = new Array( 236 );
        var lastDraw = (new Date).valueOf();

        function heavyloadFunction() {
            var entry = sqlData[ i ]

            // do something with the entry
            for ( var n = 0; n < 2000; n++ ) {
                for ( var h = 0; h < sqlData.length; h++ ) {
                    var cEntry = sqlData[h]
                    cEntry = Math.random()
                }
            }

            // finish entry work

            if(i < sqlData.length){
                i++;
                continueExecution = true;
            }else{
                console.log("finished")
                continueExecution = false;
            }
        }

        function drawProgress( progress ) {
            var percentageComplete = Math.floor( ( progress.current / progress.maximum ) * 100 ) + "%";
            progressBar.style.width = percentageComplete
        }

        function shouldReDraw(){
            var dNow = (new Date).valueOf();
            if(dNow - lastDraw > 16){
                // around 60fps
                lastDraw = dNow;
                return true;
            }else{
                return false;
            }
        }

        function excutionLoop() {
            heavyloadFunction();

            if ( continueExecution ) {
                if(shouldReDraw()){
                    drawProgress({
                        current: i,
                        maximum: sqlData.length
                    })

                    window.setTimeout( excutionLoop, 0 )
                }else{
                    excutionLoop()
                }
            }else{
                drawProgress({
                    current: i,
                    maximum: sqlData.length
                })
            }           
        }

        excutionLoop();
    </script>
</body>
</html>