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