[英]How to force repaint in JS?
我想要达到的目标:
这是剥离的代码:
<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,但是没有任何效果。
这将是一个绘制复杂数学对象(分形)的程序,我将使用canvas而不是div,但是我简化了上面的示例。 由于将来会有图形界面,因此不能选择使用“ alert()”-计算完成后,“计算进行中”屏幕应立即变为“完成”。
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
事件)。
如果磁贴不是很小,那么开销是可以接受的,仍然可以合理地响应重新绘制和用户交互来保持页面。
您需要等待一毫秒或与Worker进行计算。
第一个示例可能是最简单的,而不是直接调用calc
,而是创建一个新函数
function caller() {
// insert "calculation in progress" in the body
setTimeout(calc, 1);
}
然后呼叫caller
。
由于现代浏览器可能会延迟重新绘制以获得更好的帧速率,因此带有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.
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.