fire
fire
by Csaba Hellinger
HTML
<canvas id="canvas" width="400" height="200"></canvas>
CSS
body {
background: #222;
}
canvas {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
JavaScript
const FLAMES = 14;
const FLAME_WIDTH = 20;
const TEMP_MIN = 200;
const TEMP_MAX = 255;
const canvas = document.getElementById('canvas');
const width = canvas.offsetWidth;
const height = canvas.offsetHeight;
const ctx = canvas.getContext('2d');
const fire = new Uint8ClampedArray(width * height).fill(0);
// generate color map
const stops = [
[0, 0,0,0],
[90, 255,0,0],
[130, 255,155,0],
[230, 255,255,255],
[255, 255,255,255]
];
let stop = -1;
const mapMix = (min,max,mix) => Math.round(min + (max - min) * mix);
const map = new Array(256).fill(0).map((x,index) => {
if (stops[stop+1][0] === index) {
stop += 1;
return stops[stop].slice(1);
}
const [min, minR, minG, minB] = stops[stop];
const [max, maxR, maxG, maxB] = stops[stop+1];
const mix = (index-min) / (max-min);
return [
mapMix(minR, maxR, mix),
mapMix(minG, maxG, mix),
mapMix(minB, maxB, mix)
];
});
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, width, height);
const MAX = 5000;
let counter = 0;
function draw() {
// draw flame roots
for (let f=0; f<FLAMES; f+=1) {
const flameX = Math.trunc(Math.random() * (width-FLAME_WIDTH));
const flameLeft = (height-1)*width + flameX;
const flameRight = flameLeft + FLAME_WIDTH;
const temp = TEMP_MIN + Math.random() * (TEMP_MAX-TEMP_MIN);
for (let i=flameLeft; i<flameRight; i+=1) fire[i] = temp;
}
// blur up
for (let y=0; y<height; y+=1) {
const yIndex = y * width;
const upIndex = yIndex - width;
const downIndex = yIndex + width;
for (let x=0; x<width; x+=1) {
fire[x + yIndex] = (
fire[x + upIndex] +
fire[x-1 + downIndex] +
fire[x + downIndex] +
fire[x+1 + downIndex]
) >> 2;
}
}
// write to canvas
const imgData = ctx.createImageData(width, height);
const data = imgData.data;
for (i=0; i<width*height; i+=1) {
const [r,g,b] = map[fire[i]];
data[i*4] = r;
data[i*4+1] = g;
data[i*4+2] =...