2016-06-21 75 views
0

我想实现:如何在JS中强制重绘?

  1. 用户点击一个元素
  2. 在屏幕上显示屏幕上的“正在计算”
  3. 系统执行耗时的数学计算
  4. 屏幕显示结果( “完成”)

这里的剥离代码:

<div id ="di" onclick="calc()">initial</div> 
<script> 

function calc() 
{ 
var n,a=0; 
document.getElementById('di').textContent="calculation in progress"; 
for(n=0;n<1000000000;n++) // Here's the time consuming calculation 
    { 
    a=a+n; // for clarity's sake, I removed a complicated math formula here 
    } 
document.getElementById('di').textContent="done "+a; 
} 
</script> 

当我运行它并单击div时,它需要一段时间,然后将文本更改为“完成”,因此用户看不到“计算正在进行中”消息 - 这是我的问题。

要强制重画屏幕以在计算开始前显示消息,其他线程建议修改CSS,隐藏并立即取消隐藏元素或使用setTimeout,但没有任何工作。

这将是一个绘制复杂的数学对象(分形)的程序,我将使用画布而不是div,但我简化了上面的示例。由于未来的图形界面,使用“alert()”不是一个选项 - 完成计算后,“计算进行中”屏幕应立即变为“完成”。

回答

0

您需要等待一毫秒或者使用工人进行计算。

第一个例子可能是最简单的,而不是直接调用calc,创建一个新的功能

function caller() { 
    // insert "calculation in progress" in the body 
    setTimeout(calc, 1); 
} 

然后调用caller

+0

您还需要在'setTimeout'调用之前设置双DIV文本,它实际上更新 – Zack

+0

这是你的意思?它仍然不起作用:

initial
Fractal

+0

@分形阅读示例,评论也是 –

1

IMO一种简单的方法来处理这个问题是让你的计算由定时器功能中的“小”豆腐块进行,例如:

function calcFractal(x0, y0, x1, y1) { 
    ... compute the fractal for the tile (x0, y0)-(x1, y1) ... 
} 

var x = 0, y = 0; 

function nextTile() { 
    calcFractal(x, y, x+tw, y+th); 
    x += tw; 
    if (x >= width) { 
     x = 0; 
     y += th; 
    } 
    if (y < height) setTimeout(nextTile, 0); 
} 

nextTile(); 

这使您可以显示进度(包括例如低分辨率的分形,计算的百分比)并且允许中断(例如,在停止按钮上的onclick事件)。

如果瓷砖不是很小,则开销可以接受,仍然可以保持页面对重绘和用户交互的合理响应。

0

由于现代浏览器可能会延迟重绘以获得更好的帧速率,因此带有setTimeout的版本可能无法在超时时间过短的情况下工作。

如果可能,您需要使用requestAnimationFrame。如果它不可行,那么@Bálint的答案应该可以工作,但是会有更大的超时(在我的Firefox测试中,它的开始工作时间是20-30附近的超时)。实际的超时值是依赖于浏览器(过于依赖,可能系统)

function very_long_func(){ 
    el= document.getElementById('di'); 

    requestAnimationFrame(function(){ 
     //edit dom for new frame; 
     el.textContent = 'calculation in progress' 
     //browser will wait for this functions end, before start redraw. 
     //So actual calucation must run outside of it 
     setTimeout(function_with_actual_calculation, 1); 

    }) 
} 
function function_with_actual_calculation(){ 
    //..your math here + updating textContent to "done" in the end. 
}