2013-06-10 2 views
0

Я хотел бы сделать простой эффект огня с помощью Canvas. На данный момент я не понимаю аспекта кодирования использования двойного буфера в этом контексте (ошибка). Я сделал код, используя скобки, и код JSLint прошел хорошо. Ошибка: «Невозможно установить свойство« NaN »неопределенного». Что я делаю неправильно в этом примере?Бланк двойной буферизации для эффекта огня

/*global document: false */ 
/*global setInterval */ 

function getPixel(imageData, x, y) { 
    "use strict"; 
    var index = 0, r, g, b; 

    index = (x + y * imageData.width) * 4; 
    r = imageData.data[index]; 
    g = imageData.data[index + 1]; 
    b = imageData.data[index + 2]; 

    return [r, g, b]; 
} 

function setPixel(imageData, x, y, r, g, b, a) { 
    "use strict"; 
    var index = 0; 
    index = (x + y * imageData.width) * 4; 
    imageData.data[index]  = r; 
    imageData.data[index + 1] = g; 
    imageData.data[index + 2] = b; 
    imageData.data[index + 3] = a; 
} 

var element = document.getElementById("canvas"); 
var c  = element.getContext("2d"); 
var w  = element.width; 
var h  = element.height; 

// set buffer 
var offScreenCanvas   = document.createElement('canvas'); 
offScreenCanvas.width  = w; 
offScreenCanvas.height  = h; 
var ctxOffscreen   = offScreenCanvas.getContext('2d'); 

function init() { 
    "use strict"; 
    var x, y, i, j, r, g, b; 

    for (j = 0; j < 10; j += 1) { 
     for (i = 0; i < 800; i += 1) { 
      x = i; 
      y = j; 
      r = 255 - Math.round(Math.random() * 50); 
      g = 0; 
      b = 0; 
      setPixel(ctxOffscreen, x, y, r, g, b, 255); 
     } 
    } 

    c.putImageData(ctxOffscreen, 0, 0); 
} 

function animation() { 
    "use strict"; 
    var a1, a2, a3, a4, r, g, b, i, j; 

    // draw 
    for (j = 9; j < 100; j += 1) { 
     for (i = 0; i < 800; i += 1) { 
      a1 = getPixel(offScreenCanvas, i, j - 1); 
      a2 = getPixel(offScreenCanvas, i, j + 1); 
      a3 = getPixel(offScreenCanvas, i - 1, j); 
      a4 = getPixel(offScreenCanvas, i + 1, j); 

      r = Math.round((a1[0] + a2[0] + a3[0] + a4[0])/4); 
      g = Math.round((a1[1] + a2[1] + a3[1] + a4[1])/4); 
      b = Math.round((a1[2] + a2[2] + a3[2] + a4[2])/4); 

      setPixel(offScreenCanvas, i, j, r, g, b, 255); 
     } 
    } 

    // copy buffer onto the canvas 
    c.putImageData(offScreenCanvas, 0, 0); 
} 

init(); 
setInterval(animation, 20); 

Ошибка в определении setPixel.

imageData.data[index]  = r; 

ответ

1

Во-первых, подружитесь с отладчиком. Это поможет вам. Я нахожу, что на Chrome (нажмите Ctrl-Shift-I) проще всего работать, но ваш пробег может отличаться.

Во-вторых, размещение вашего html с шириной и высотой холста было бы полезно. Из вашего кода я выводил, что это было, по-видимому, 800x100.

Итак, я думал, что переменная imageData, переданная в setPixel, была как-то неопределенной, но отладчик показал мне другое. Это правильно определенный context2d. Но это приводит к проблеме, которую вы испытываете.

Вы правильно передаете переменную ctxOffscreen в setPixel, но в setPixel вы предполагаете, что это объект imageData. Это не. Они разные.

Поскольку вы используете два контекста, вы, вероятно, захотите просто getImageData вашего внеэкранного контекста. (Вы можете избежать двух контекстов и просто два imageDatas на вместо вызова c.createImageData, но я пойду с тем, что вы в настоящее время есть.)

сразу после var ctxOffscreen line добавить новый:

var imgData = ctxOffscreen.getImageData(0, 0, w, h); 

Передайте это в setPixel и getPixel вместо (ctxOffscreen), например

setPixel(imgData, y, y, r, g, b, 255); 

Отъезд FIDDLE. Он работает. Я думаю, это может работать так, как вы хотите.

+0

Большое спасибо за помощь! :) – user1948027