admin管理员组

文章数量:1312848

I am trying to run some code after I change the background of an element. I'd like to run the code after the background is changed visually, not just internally. Thus I'd like to wait for a repaint. I tried doing this using rAF, but that does not seem to be the correct way, because the code gets executed before the background color is changed visually (talking about milliseconds though).

I tried to achieve my goal with the following code (without luck):

  requestAnimationFrame(() => {
    document.getElementsByTagName("body")[0].style.backgroundColor =
      "rgb(0, 75, 75)";
      requestAnimationFrame(() => {
        socket.emit("notify-black");
      });
  });

What would be the correct way of waiting for the repaint?

I am trying to run some code after I change the background of an element. I'd like to run the code after the background is changed visually, not just internally. Thus I'd like to wait for a repaint. I tried doing this using rAF, but that does not seem to be the correct way, because the code gets executed before the background color is changed visually (talking about milliseconds though).

I tried to achieve my goal with the following code (without luck):

  requestAnimationFrame(() => {
    document.getElementsByTagName("body")[0].style.backgroundColor =
      "rgb(0, 75, 75)";
      requestAnimationFrame(() => {
        socket.emit("notify-black");
      });
  });

What would be the correct way of waiting for the repaint?

Share Improve this question asked Apr 17, 2020 at 21:38 Bram VanbilsenBram Vanbilsen 6,50514 gold badges57 silver badges96 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 8

requestAnimationFrame will run its callback just before the next repaint. Put the code you want to run in a setTimeout inside that, since the timeout callback will run almost immediately after the repaint finishes.

You can also use document.body instead of document.getElementsByTagName("body")[0]:

requestAnimationFrame(() => {
  document.body.style.backgroundColor = "rgb(0, 75, 75)";
  requestAnimationFrame(() => {
    setTimeout(() => {
      socket.emit("notify-black");
    });
  });
});

Live demo, using alert (which blocks) instead of socket.emit:

requestAnimationFrame(() => {
  document.body.style.backgroundColor = "rgb(0, 75, 75)";
  requestAnimationFrame(() => {
    setTimeout(() => {
      alert("notify-black");
    });
  });
});

Another example code that takes a screenshot using html2canvas. Open up example., open your console, and run the following:

const script = document.body.appendChild(document.createElement('script'));
script.src = 'https://html2canvas.hertzen./dist/html2canvas.js'
script.onload = () => {
  requestAnimationFrame(() => {
    document.body.style.backgroundColor = "rgb(0, 75, 75)";
    requestAnimationFrame(() => {
      setTimeout(() => {
        html2canvas(document.querySelector("body")).then(canvas => {
          document.write('<img src="'+canvas.toDataURL("image/png")+'"/>');
        });
      });
    });
  });
};

The best reliable and working answer including explanation i found, remend reading this https://www.webperf.tips/tip/measuring-paint-time/

And for reference in case the link isn't available anymore at some point:

/**
 * Runs `callback` shortly after the next browser Frame is produced.
 */
function runAfterFramePaint(callback) {
    // Queue a "before Render Steps" callback via requestAnimationFrame.
    requestAnimationFrame(() => {
        const messageChannel = new MessageChannel();

        // Setup the callback to run in a Task
        messageChannel.port1.onmessage = callback;

        // Queue the Task on the Task Queue
        messageChannel.port2.postMessage(undefined);
    });
}

Use the following way:

elem.style.backgroundColor = 'red';
runAfterFramePaint(() => {
    elem.style.backgroundColor = 'blue';
});

本文标签: htmlWaiting for repaint in JavascriptStack Overflow