Reputation: 10896
I am used to using GLUT's PostRedisplay and (App|UI)Kit's setNeedsDisplay methods for requesting a new display event to be posted to the event queue when the app wishes to redraw a scene. I haven't found a counterpart with HTML5's Canvas element. For example, I am currently just calling my display()
function directly when I want to redraw to the canvas:
function mouseMove(event) {
if (mouseDrag) {
// update camera position
display();
}
}
The display()
function renders the scene (which can be expensive):
function display() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// issue WebGL calls to redraw scene
gl.flush();
}
Most systems I am used to will coalesce multiple display events into one event if multiple rendering requests occur before the last rendering is finished. What I am doing above can be problematic if a long stream of display()
calls outpace the rendering speed.
Anyway, what is the correct way to redraw canvas elements effeciently?
You can see the demo app I am working on here (if you have WebGL enabled).
Update : Following the answer below I now use RequestAnimationFrame
and use the return value as a flag to indicate that a request has already been made. When the scene is rendered I clear the flag so further requests can be made:
var requestId = 0; // id of current requestAnimationFrame request (0 = no request)
function mouseMove(event) {
if (mouseDrag) {
// update camera position
if (requestId)
requestId = requestAnimationFrame(display);
else
console.log("request already in queued"); // test
}
}
function display() {
requestId = 0;
// redraw scene
}
Noting the log messages I get this does indeed coalesce multiple requests. This seems like a great approach. Are there any other solutions?
Upvotes: 1
Views: 485
Reputation: 10675
You can use requestAnimationFrame(display)
to set a callback (in this case, display
) to be called at the next repaint.
It's up to you to only call it once when waiting for a repaint (at the repaint, it will do the callback for each call you made to requestAnimationFrame
). It's also up to you to request another animation frame if you want to animate continuously.
Upvotes: 2