On rare occasion, <canvas> doesn't redraw
Asked Answered
E

2

8

I use <canvas> to draw all notes and glyphs in my music education web apps: http://www.musictheory.net/exercises/keysig/bc98yy

A Firefox 15.0.1 user has reported that sometimes the exercise goes on to the next question, but the canvas still shows the previous question. I have seen this occur in testing one time (out of ~500 questions).

When it occurs, the canvas has been cleared via both canvas.width = canvas.width and a call to .clearRect on the context and glyphs have been drawn in JavaScript via .beginPath, .quadraticCurveTo, .closePath, etc. However, it seems like the canvas's backing buffer never gets flushed/drawn into the window.

I have seen bug reports in the past regarding similar issues:

I can force a redraw by doing a DOM hack such as inserting a text node as a child of the canvas, and then removing it on the next run loop cycle, or modifying the background-color or padding of the canvas. This seems heavy-handed, however, and I keep having the nagging feeling that I'm missing something obvious.

My drawing code is simple enough:

canvas.width = width;
ctx.clearRect(0, 0, width, height);
ctx.save();
// Lots of drawing code here
ctx.restore()
ctx.clearRect(0, 0, 1, 1); // Helped force a repaint on some older WebKit browsers?

I have ensured that the number of .save and .restore calls are balanced.

1) I am calling this code directly in response to an onclick event handler. Should I instead be using requestAnimationFrame or setTimeout to perform the drawing on a future run loop cycle?

2) I'm not missing something obvious, like a canvas.pleaseRepaintNow() API, right?

3) Have other people encountered similar issues and resorted to DOM modification to force redraws?

Exotic answered 5/10, 2012 at 23:7 Comment(0)
N
4

Add context.stroke(); to the last line of your onLoad function, it fixes a bug in Firefox. Otherwise changes to the canvas don't render until the window is redrawn.

It worked in my case at least.

window.onload = function() {
   canvas = document.getElementById("canvas");
   context = canvas.getContext("2d");
   //Code here...
   context.stroke();
}
Nootka answered 15/10, 2012 at 22:30 Comment(2)
Do you know what Firefox versions this affects? Is there an entry in the Firefox Bugzilla for it? Thanks!Exotic
It effects version 15, and has been reported already. It is interesting that they say the issue occurs for chrome as well, even though it is more up to date.Nootka
C
1

I tried to get the bug to happen but after madly clicking in Firefox for awhile, I never saw it. This is how I clear the canvas which seems to work, but take it with a grain of salt since I can't get the bug to occur I also can't check to see if this fixes anything...

// Store the current transformation matrix
ctx.save();

// Use the identity matrix while clearing the canvas
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);

// Restore the transform
ctx.restore();
Cyruscyst answered 9/10, 2012 at 3:30 Comment(4)
Upvoting due to the setTransform(), which I definitely was missing. The issue remains, however :(Exotic
Do you have a method to make it reliably happen? Or just keep clicking?Cyruscyst
I do not, it only happened on my machine once. A user can reliably reproduce it within a 100 questions, however (running Firefox 15.0.1 on OS X 10.7 on a 2011 MacBook Pro). I have tried to match his configuration as close as possible, but with no luck in reproducing.Exotic
Have you considered asking the user to disable all extensions and addons, in case some misbehaving third party code is the culprit?Arliearliene

© 2022 - 2024 — McMap. All rights reserved.