2009-06-11 2 views
12

Так что я работал над этим небольшим экспериментом javascript, и мне нужен виджет для отслеживания FPS этого. Я портировал виджет, который я использовал с ActionScript 3 для Javascript, и, похоже, он отлично работает с Chrome/Safari, но в Firefox выбрасывается исключение.Firefox бросает исключение с HTML Canvas putImageData

Это эксперимент:

Depth of Field

Это ошибка:

[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"] 

линия, которая complaning об это одна:

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

}

Любые идеи? Заранее спасибо.

ответ

0

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

See here

+0

Вы правы, у меня были неправильные параметры. Тем не менее, я изменил их, поэтому он использует правильные параметры и по-прежнему дает ту же ошибку. – 2009-06-11 17:11:34

1

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

4

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

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

+0

Это была моя проблема. Вместо того, чтобы отсекать мои данные, я просто сделал холст больше, и исключение перестало быть брошенным. –

0

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

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

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

+0

В одном из моих проектов я добавил попытку/уловить функцию putImageData. В худшем случае вы получаете рамку без изображения, а не сломанную программу. Это не решение, но да .. – Jacksonkr

0

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

7

Это ошибка в Firefox. Mozilla knows about it.Вот обходной путь:

  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 
    
+0

Этот ответ спас мне половину дня работы. Спасибо. – donohoe

+0

Все еще действительное исправление, просто столкнулось с этой проблемой с Mac FF4.0.1. –

1

У меня была аналогичная проблема с 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); 
Смежные вопросы