The original reverse-engineering done by Samuel Villarreal
was already using javascript. I assume by "plain" you mean you removed easeljs library for canvas management and added buttons?
Yes Fabien! Also thanks for your article, it really inspired me to code my own version. Had a great time! I'm planning to make a video about all this and I will tweet you when it's published.
Maybe it wasn't clear in the original article [1], but what you see inline are javascript implementations of the effect - there is a link to the source code at the end:
The blog post is sadly not easy to follow along to try to do an implementation due to what appear to be minor description mistakes or poor writing which confuses.
It switches from saying that 0 in the map represents white, to saying it is black, and then in the loop it states that the first row isn't changed but the loop pseudo-code skips over the first row only to then overwrite that first row in the code:
The comment, "Notice that line 0 is not updated" doesn't make clear it's not talking about the start of the buffer:
It clearly changes index 0. In fact if line 0 is the 'generator' row it is in fact the last line in the buffer and the description of why it doesn't change is wrong: It's not unchanged because the loop starts at 1, it's unchanged because the loop is modifying 'src-FIRE_WIDTH'.
Maybe some of the description or pseudo-code described are describing two different implementations one of which maybe is working with a reversed buffer.
The principle however is clear, and it is interesting to see in the browser, although I'm sticking to just loading it into a canvas directly with CanvasRenderingContext2D.putImageData which lets you directly write an image buffer (noting that it is RGBA so 4 bytes per drawn pixel).
In fact the 'cleaned up' version linked at the bottom appears to do the same.
I first learned to do this effect in 1999 thanks to the incredible Denthor/Asphexia tutorials. I looked forward to new releases of these that my friend would (somehow) get and give to me on a floppy disk.
I remember those! Incredibly accessible. Also remember writing Den(e?)thor as an insecure, new-to-the-internet 16-year old asking whether more tutorials were in production. Never received an answer, unfortunately.
It's a bit slow. I suggest 1) Use existing table instead of creating a new table at each frame/interval. 2) Or use Canvas because DOM is so slow 3) requestAnimationFrame instead of setInterval
You always get surprises when optimizing, for example IE11 and probably other browsers use DOM optimization with hardware acceleration, so keeping it as a table, and just changing the bgColor instead of creating a new table, might be fast, fast enough, or even faster then canvas. As for imageData vs fillRect I would go with fillRect first as it makes it easier to scale to the clients pixelRatio, eg you want to scale to 200% on a device that has a pixel ratio of 2 in order to make it look crisp. In my experience, manipulating single pixels are sometimes also slower! But if you really want to get advanced you could divide the screen up in different pieces and use many (off-screen) canvas's and/or web workers, but it would probably only work on Chrome, and then you would operate on the imageData buffer.
Yeah it’d probably require implementing all approaches and benchmarking in various browsers.
For scaling I find using CSS works well instead of scaling the canvas. Most browsers support `image-rendering: pixelated` now. Of course no MS browser does.
I’ve always been impressed with canvas. I recently wrote a little app that creates 1024 16x16 canvases and I’ve yet to find any browser (including mobile) break a sweat.