如何在JS强制重绘?

时间:2016-06-21 20:21:22

标签: javascript html repaint

我想要实现的目标:

  1. 用户点击元素
  2. 屏幕显示"正在进行的计算"屏
  3. 系统执行耗时的数学计算
  4. 屏幕显示结果("完成")
  5. 这是剥离的代码:

    id

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

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

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

3 个答案:

答案 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个事件)。

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

答案 1 :(得分:0)

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

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

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

然后拨打caller

答案 2 :(得分: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.
}