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?

iccir
  • 5,078
  • 2
  • 22
  • 34

2 Answers2

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();
}
Ross Gatih
  • 649
  • 4
  • 9
  • Do you know what Firefox versions this affects? Is there an entry in the Firefox Bugzilla for it? Thanks! – iccir Oct 15 '12 at 23:42
  • It effects version 15, and has been reported [already](https://bugzilla.mozilla.org/show_bug.cgi?id=790738). It is interesting that they say the issue occurs for chrome as well, even though it is more up to date. – Ross Gatih Oct 16 '12 at 05:38
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();
Bill
  • 25,119
  • 8
  • 94
  • 125
  • Upvoting due to the setTransform(), which I definitely was missing. The issue remains, however :( – iccir Oct 10 '12 at 06:30
  • Do you have a method to make it reliably happen? Or just keep clicking? – Bill Oct 10 '12 at 06:34
  • 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. – iccir Oct 10 '12 at 06:52
  • Have you considered asking the user to disable all extensions and addons, in case some misbehaving third party code is the culprit? – Kelvin Oct 15 '12 at 22:34