В редких случаях ‹холст› не перерисовывается

Я использую <canvas> для рисования всех нот и глифов в своих веб-приложениях для музыкального образования: http://www.musictheory.net/exercises/keysig/bc98yy

Пользователь Firefox 15.0.1 сообщил, что иногда упражнение переходит к следующему вопросу, но на холсте по-прежнему отображается предыдущий вопрос. Я видел это при тестировании один раз (из ~ 500 вопросов).

Когда это происходит, холст очищается как с помощью canvas.width = canvas.width, так и с помощью вызова .clearRect в контексте, а глифы рисуются в JavaScript с помощью .beginPath, .quadraticCurveTo, .closePath и т. д. Однако кажется, что резервный буфер холста никогда не очищается/отрисовывается. в окно.

Я видел отчеты об ошибках в прошлом, касающиеся подобных проблем:

Я могу принудительно перерисовать, выполнив хак DOM, например вставив текстовый узел в качестве дочернего элемента холста, а затем удалив его в следующем цикле выполнения или изменив цвет фона или отступы холста. Однако это кажется неуклюжим, и у меня все еще есть ноющее чувство, что я упускаю что-то очевидное.

Мой код рисования достаточно прост:

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?

Я убедился, что количество вызовов .save и .restore сбалансировано.

1) Я вызываю этот код непосредственно в ответ на обработчик событий onclick. Должен ли я вместо этого использовать requestAnimationFrame или setTimeout для выполнения рисования в будущем цикле цикла выполнения?

2) Я не упускаю чего-то очевидного, например canvas.pleaseRepaintNow() API, верно?

3) Сталкивались ли другие люди с подобными проблемами и прибегали ли к модификации DOM для принудительной перерисовки?


person iccir    schedule 05.10.2012    source источник


Ответы (2)


Добавьте context.stroke(); в последнюю строку вашей функции onLoad, это исправляет ошибку в Firefox. В противном случае изменения на холсте не отображаются до тех пор, пока окно не будет перерисовано.

По крайней мере, в моем случае это сработало.

window.onload = function() {
   canvas = document.getElementById("canvas");
   context = canvas.getContext("2d");
   //Code here...
   context.stroke();
}
person Ross Gatih    schedule 15.10.2012
comment
Знаете ли вы, на какие версии Firefox это влияет? Есть ли для этого запись в Firefox Bugzilla? Спасибо! - person iccir; 16.10.2012
comment
Это влияет на версию 15, о чем сообщалось уже. Интересно, что они говорят, что проблема возникает и для хрома, хотя он более свежий. - person Ross Gatih; 16.10.2012

Я пытался исправить ошибку, но после безумного клика в Firefox я так и не увидел ее. Вот как я очищаю холст, который, кажется, работает, но воспринимаю его с недоверием, так как я не могу вызвать ошибку, я также не могу проверить, исправляет ли это что-нибудь...

// 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();
person Bill    schedule 09.10.2012
comment
Upvoting из-за setTransform(), которого мне определенно не хватало. Однако проблема остается :( - person iccir; 10.10.2012
comment
У вас есть способ сделать это надежно? Или просто продолжать нажимать? - person Bill; 10.10.2012
comment
У меня нет, это было только на моей машине один раз. Однако пользователь может достоверно воспроизвести его, ответив на 100 вопросов (запустив Firefox 15.0.1 в OS X 10.7 на MacBook Pro 2011 года). Я пытался максимально точно воспроизвести его конфигурацию, но безуспешно. - person iccir; 10.10.2012
comment
Рассматривали ли вы вопрос о том, чтобы попросить пользователя отключить все расширения и надстройки на случай, если виновником является неправильный сторонний код? - person Kelvin; 16.10.2012