Firefox бросает исключение с HTML Canvas putImageData
Итак, я работал над этим небольшим экспериментом javascript, и мне нужен виджет для отслеживания FPS. Я портировал виджет, который я использовал с ActionScript 3 в Javascript, и, похоже, он отлично работает с Chrome/Safari, но Firefox исключает исключение.
Это эксперимент:
Глубина поля
Это ошибка:
[Exception... "An invalid or illegal string was specified" code: "12" nsresult: "0x8053000c (NS_ERROR_DOM_SYNTAX_ERR)" location: "http://mrdoob.com/projects/chromeexperiments/depth_of_field__debug/js/net/hires/debug/Stats.js Line: 105"]
Сплошная строка:
graph.putImageData(graphData, 1, 0, 0, 0, 69, 50);
Это дрянной код для "прокрутки" растровых пикселей. Идея состоит в том, что я рисую только несколько пикселей слева от растрового изображения, а затем в следующем кадре копирую все растровое изображение и вставляю его на пиксель вправо. Обычно эта ошибка возникает из-за того, что вы вставляете растровое изображение больше, чем источник, и оно выходит за пределы, но теоретически это не должно быть так, как я определяю 69 как ширину прямоугольника для вставки (будучи растровое изображение шириной 70 пикселей).
И это полный код:
var Stats = {
baseFps: null,
timer: null,
timerStart: null,
timerLast: null,
fps: null,
ms: null,
container: null,
fpsText: null,
msText: null,
memText: null,
memMaxText: null,
graph: null,
graphData: null,
init: function(userfps)
{
baseFps = userfps;
timer = 0;
timerStart = new Date() - 0;
timerLast = 0;
fps = 0;
ms = 0;
container = document.createElement("div");
container.style.fontFamily = 'Arial';
container.style.fontSize = '10px';
container.style.backgroundColor = '#000033';
container.style.width = '70px';
container.style.paddingTop = '2px';
fpsText = document.createElement("div");
fpsText.style.color = '#ffff00';
fpsText.style.marginLeft = '3px';
fpsText.style.marginBottom = '-3px';
fpsText.innerHTML = "FPS:";
container.appendChild(fpsText);
msText = document.createElement("div");
msText.style.color = '#00ff00';
msText.style.marginLeft = '3px';
msText.style.marginBottom = '-3px';
msText.innerHTML = "MS:";
container.appendChild(msText);
memText = document.createElement("div");
memText.style.color = '#00ffff';
memText.style.marginLeft = '3px';
memText.style.marginBottom = '-3px';
memText.innerHTML = "MEM:";
container.appendChild(memText);
memMaxText = document.createElement("div");
memMaxText.style.color = '#ff0070';
memMaxText.style.marginLeft = '3px';
memMaxText.style.marginBottom = '3px';
memMaxText.innerHTML = "MAX:";
container.appendChild(memMaxText);
var canvas = document.createElement("canvas");
canvas.width = 70;
canvas.height = 50;
container.appendChild(canvas);
graph = canvas.getContext("2d");
graph.fillStyle = '#000033';
graph.fillRect(0, 0, canvas.width, canvas.height );
graphData = graph.getImageData(0, 0, canvas.width, canvas.height);
setInterval(this.update, 1000/baseFps);
return container;
},
update: function()
{
timer = new Date() - timerStart;
if ((timer - 1000) > timerLast)
{
fpsText.innerHTML = "FPS: " + fps + " / " + baseFps;
timerLast = timer;
graph.putImageData(graphData, 1, 0, 0, 0, 69, 50);
graph.fillRect(0,0,1,50);
graphData = graph.getImageData(0, 0, 70, 50);
var index = ( Math.floor(Math.min(50, (fps / baseFps) * 50)) * 280 /* 70 * 4 */ );
graphData.data[index] = graphData.data[index + 1] = 256;
index = ( Math.floor(Math.min(50, 50 - (timer - ms) * .5)) * 280 /* 70 * 4 */ );
graphData.data[index + 1] = 256;
graph.putImageData (graphData, 0, 0);
fps = 0;
}
++fps;
msText.innerHTML = "MS: " + (timer - ms);
ms = timer;
}
}
Любые идеи? Спасибо заранее.
Ответы
Ответ 1
Это ошибка в Firefox. Mozilla знает об этом. Здесь обходной путь:
-
Создайте новый холст в памяти:
var spriteCanvas = document.createElement('canvas');
-
Установите высоту/ширину холста на высоту/ширину вашего изображения:
spriteCanvas.setAttribute('width', 20);
spriteCanvas.setAttribute('height', 20);
-
Поместите данные изображения в холст в позиции (0,0):
spriteCanvas.getContext('2d').putImageData(imageData, 0, 0);
-
В контексте вашего основного холста нарисуйте свой холст-спрайт с помощью drawImage, используя любую позицию на экране или вне экрана:
context.drawImage(spriteCanvas, 50, 100); // clipping is allowed
Ответ 2
Да, эта ошибка возникает при использовании (get | put) ImageData с краев холста.
Для моей встречи с этой проблемой я просто добавил некоторую логику отсечения, которая проверяет края области, которые нужно нарисовать по краям холста, и при необходимости скопирует ее, только рисовая видимую область. Кажется, что проблема была устранена.
Ответ 3
У меня была такая же ошибка, потому что значение, которое я пытался установить в значение graphData.data [index], было строкой, а не целым числом.
Чтобы исправить это, я преобразовал строку в целое число с parseInt().
Ответ 4
У меня была аналогичная проблема с drawImage() при попытке нарисовать плитку на холсте того же размера следующим образом:
var image = new Image();
image.onload = function() {
context.drawImage(image, 0, 0, this.tileSize, this.tileSize);
}
image.src = this.baseURL + tileId;
Проблема исчезла, когда я удалил параметры высоты и ширины из вызова и использовал это:
context.drawImage(image, 0, 0);
Ответ 5
Я думаю, вам нужно указать еще два аргумента для putImageData: width и height.
Смотрите здесь
Ответ 6
Я занимаюсь этой проблемой в течение нескольких дней (в firefox). Лучшей идеей, которую я мог бы придумать, является динамическое удаление пикселей, которые уходят с экрана. Я беспокоюсь, что для этого потребуется слишком много CPU. надеюсь, кто-то придумает лучшую идею:/
но повторить, я видел эту ошибку только тогда, когда putImageData пытается нарисовать ЛЮБОЙ пиксель за пределами периметра холста. например. любое значение x или y, 0.
- во втором чтении -
Похоже, вы уже изменяете размеры своих данных изображения. Вы можете попробовать размер изображения до 68 пикселей, если вы находитесь в контейнере на 70 пикселей? Наверное, не получится, но стоит попробовать.
Ответ 7
Это уже устарело, но это ТОЛЬКО дает мне проблемы с FF на окнах. FF на Mac работает, как это должно быть.