javascriptjquerycsscss-animationshtml5-animation

How to force browser repaint and avoid UI update delay?


I need the browser to update my UI before a long(er) operation is done. Currently the browser is waiting until after everything is complete and then updating the UI, which means UI freezes for 1-2 seconds then updates.

So, user clicks button in UI, then this code executes:

$('#mybutton').click(function(e) {

e.preventDefault();// prevent the default anchor functionality

$('#mainctrldiv').css('display', 'none');
$('#otherctrldiv').css('display', 'block');

var img = $('<img id="spareimg" style="display:none;">');
img.attr('src', canvas.getActiveObject().toDataURL()); // This is causing the delay!
img.appendTo('body');
}

It's the canvas.getActiveObject().toDataURL() (a FabricJS function) that is taking the time. I want this to happen after the 2 divs have been visibly displayed to the user, to they don't notice. Need this to work in all commonly used browsers out there! (mobile as well as desktop).

Research suggested that reading the css display properties immediately after setting them would force the browser to repaint so I added in the following code straight after setting these properties but the delay still occurred:

$('#mainctrldiv').css('display');
$('#otherctrldiv').css('display');

Many thanks for any suggestions!


Solution

  • Try using setTimeout with zero delay, it will push these to the end of the thread. You can also try adding some delay if zero delay doesn't work for you. But I am not sure if that exact line is causing the issue, if it is post another question on how to optimise and decrease the time.

    $('#mybutton').click(function(e) {
      e.preventDefault(); // prevent the default anchor functionality
      $('#mainctrldiv').css('display', 'none');
      $('#otherctrldiv').css('display', 'block');
      setTimeout(function() {
        var img = $('<img id="spareimg" style="display:none;">');
        img.attr('src', canvas.getActiveObject().toDataURL()); // This is causing the delay!
        img.appendTo('body');
      }, 0);
    }
    

    It's important to note that the function or code snippet cannot be executed until the thread that called setTimeout() has terminated.