Firefox выдает исключение с помощью HTML Canvas putImageData - PullRequest
12 голосов
/ 11 июня 2009

Итак, я работал над этим небольшим экспериментом с 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 как ширину прямоугольника для вставки (будучи растровое изображение шириной 70px).

И это полный код:

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;
}

}

Есть идеи? Заранее спасибо.

Ответы [ 7 ]

7 голосов
/ 01 июня 2010

Это ошибка в Firefox. Mozilla знает об этом . Вот обходной путь:

  1. Создайте новый холст в памяти:

    var spriteCanvas = document.createElement('canvas');
    
  2. Установите высоту / ширину холста в соответствии с высотой / шириной вашего изображения:

    spriteCanvas.setAttribute('width', 20);
    spriteCanvas.setAttribute('height', 20);
    
  3. Поместите данные изображения на холст в позиции (0,0):

    spriteCanvas.getContext('2d').putImageData(imageData, 0, 0);
    
  4. В контексте основного холста нарисуйте спрайт холста, используя drawImage, используя любую позицию на экране или вне экрана:

    context.drawImage(spriteCanvas, 50, 100); // clipping is allowed
    
4 голосов
/ 16 ноября 2009

Да, похоже, эта ошибка возникает при использовании (get | put) ImageData с краев холста.

Для моего знакомства с этой проблемой я просто добавил некоторую логику отсечения, которая проверяет края области, которую нужно нарисовать, по краям холста и при необходимости обрезает ее, рисуя только видимую область. Кажется, это решило проблему.

1 голос
/ 16 февраля 2011

У меня была похожая проблема с 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);
1 голос
/ 11 сентября 2009

У меня была та же ошибка, потому что значение, которое я пытался установить в graphData.data [index], было строкой, а не целым числом. Чтобы исправить это, я преобразовал строку в целое число с parseInt ().

0 голосов
/ 28 мая 2010

Это уже давно, но это ТОЛЬКО дает мне проблемы с FF на windows. FF на Mac работает как надо.

0 голосов
/ 04 мая 2010

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

но, повторюсь, я видел эту ошибку, только когда putImageData пытается нарисовать ЛЮБОЙ пиксель за пределами периметра холста. например. любое значение x или y <0. </p>

- при втором чтении - Похоже, вы уже изменяете размер изображения. Вы можете попробовать уменьшить размер изображения до 68px, если вы находитесь в контейнере 70px? Вероятно, не сработает, но стоит попробовать ..

0 голосов
/ 11 июня 2009

Я думаю, вам нужно указать еще два аргумента для putImageData: ширина и высота.

Смотрите здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...