How to force repaint in JS?

前端 未结 3 999
-上瘾入骨i
-上瘾入骨i 2020-12-21 23:53

What I am trying to achieve:

  1. user clicks on an element
  2. the screen shows the \"calculation in progress\" screen
  3. the system performs time-consu
相关标签:
3条回答
  • 2020-12-22 00:25

    You need to either wait a millisecond or do the calculations with a Worker.

    The first example is probably the easiest, instead of calling calc directly, create a new function

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

    Then call caller.

    0 讨论(0)
  • 2020-12-22 00:26

    IMO an easy way to handle this is to have your computation performed in "small" chunks by a timer function, for example:

    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();
    

    This allows you to show progress (including for example a low resolution of the fractal, the percentage of the computation) and to allow interruption (with onclick events on a stop button for example).

    If the tiles are not tiny the overhead will be acceptable, still maintaining the page reasonably responsive to both repaints and user interaction.

    0 讨论(0)
  • 2020-12-22 00:39

    Because modern browsers may delay redrawing for better frame rate, versions with setTimeout may not work with too low time-outs.

    If possible you need to use requestAnimationFrame. If its not posible then @Bálint answer should work, but with much bigger timeout (in my tests in Firefox its began work with timeout near 20-30). Actual timeout value is browser dependent (and probably system dependent too)

    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.
    } 
    
    0 讨论(0)
提交回复
热议问题