HTML5 Canvas Fire

By [Plornt] on Mar 28, 2011

Doesnt look brilliant at the moment but im off to bed at the moment, I may make a few changes.

It seems to start off weirdly in chunks then they move apart more freely and it works nicely. The reason for this is because when you click start animation it creates 1000 all at once which obviously means they need to separate apart a bit before the effect kicks in.

This one I tried a slightly different way and I hope its a tad moreoptimised. Got any tips on how I can speed it up? Say in the comments :)

Thanks to Nerbas for helping me although it was one of those moments when you ask for help then you just find it yourself xD but im still thankful since I probably wouldnt have saw it if he hadnt been there.

Demo URL: http://90.200.78.182/html5/fire.html
Goes off when I go offline!

There is one minor thing, it takes the width and height of your canvas as a template, so as such if you use this on a really wide canvas but not so high or vice versa it would look shit!

<!DOCTYPE html>
<html>
  <head>
    <title>HTML 5 FIRE</title>
  </head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
  <script> 
    var canvas;
    var context;
    var flameWindLow = 1;
    var flameWindMax = 200;
    var flameWindDiff = (flameWindMax - flameWindLow) / 2;
    var flameWiggle = 40;
    var frames = 0;
    var obj = new Array();
    $(document).ready(function () {
        canvas = document.getElementById('fire');
        context = canvas.getContext('2d');
        context.clearRect(0,0,canvas.width, canvas.height)
    });
    function Particle (speed,originX,originY) {
        //Particle Class
        this.life = rand(4,7);
        this.step = speed + 1;
        this.opacityAndSize = 0.1;
        this.markDelete = 0;
        this.originX = originX;
        this.originY = originY;
        this.speed = speed;
        this.draw = function () {
            context.beginPath();
            var l1 = findPath(this.originX,this.originY,((canvas.width / 2) + (rand(flameWindLow,flameWindMax) - flameWindDiff)),0,this.step);
            //console.log(this.originX,this.originY,this.originX,0,this.step);
            if (l1[1] >= 0 && this.life >= 0 && this.opacityAndSize >= 0) {
                //context.moveTo((l1[0] + (rand(1,flameWiggle) - (flameWiggle / 2))), l1[1]);
                //var l2 = findPath(this.originX,this.originY,((canvas.width / 2) + (rand(flameWindLow,flameWindMax) - flameWindDiff)),0,(this.step - this.speed));
                //console.log(l2);
                //context.lineTo((l2[0] + (rand(1,flameWiggle) - (flameWiggle / 2))), l2[1]);       
                context.arc(l1[0],l1[1],(250 * this.opacityAndSize),0,Math.PI*2,true);
                //context.closePath();
                context.fillStyle='rgba(255,'+rand(100,190)+','+rand(1,50)+','+this.opacityAndSize+')';
                context.fill();
                this.originX=l1[0];
                this.step += this.speed;
                this.opacityAndSize -= 0.01;
                this.life--;
            }
            else { 
                var temp = new Particle(rand(1,60),rand(1,canvas.width),canvas.height);
                obj.push(temp);
                this.markDelete = 1;
            }
        }
    }
    function findPath (x1,y1,x2,y2,step) {
            var x3 = x2 - x1; var y3 = y2 - y1;
            var length = Math.sqrt(((x3 * x3) + (y3 * y3)));
            x3 /= length; y3 /= length;
            x3 *= step; y3 *= step;
            x3 += x1; y3 += y1;
            return [x3,y3];
    }
    function rand (l,h) { 
        //Find a random number between l and h
        var rand = Math.floor((Math.random() * h) + 1); 
        while (rand < l) rand = Math.floor((Math.random() * h) + 1);  
        return rand; 
    }
    function createParticles () {
        //Create first time particles
        for (i = 1; i <= 1000; i++) {

                var temp = new Particle(rand(1,60),rand(1,canvas.width),canvas.height);
                obj.push(temp);
            obj.push(temp);
        }
    }
    function loop () {
        frames++;
        canvas.width = canvas.width;
        var len = obj.length;
            for(var i=0; i < len; i++) {

                    if (obj[i].markDelete != 1) {
                        obj[i].draw();
                    }
                    else { obj.splice(i,1); i--; len--;};
            }
        $('#frames').html(frames);
        setTimeout(function () { loop(); },10);
    }

  </script>
  <body bgcolor="black">
    <canvas id="fire" width="300" height="400">You do not have canvas </canvas>
    <br /> <div id="frames"></div> <input type="submit" value="Start Animation" onclick="createParticles();loop();" />

  </body>
</html>

Comments

Sign in to comment.
[Plornt]   -  Jun 14, 2012

Nice work... Looks good and is relatively non laggy although I cant entirely tell since I am on a beast of a computer.

Ive created a jsfiddle so people dont have to fuck about with saving on my one. http://jsfiddle.net/EHUTq/1/

It wasnt as well known when I created this.

 Respond  
clongonyc   -  Jun 14, 2012

Here's my canvas fire demo

http://chrislongo.net/html5/canvas/

 Respond  
[Plornt]   -  Mar 30, 2011

Well different versions do different things, so Ive ammended both issues and I assume its all fixed now :)

 Respond  
sunslayer   -  Mar 30, 2011

@Hawkee it works fine for me on Firefox with my edit

 Respond  
Hawkee   -  Mar 30, 2011

@[Plornt], Good work, keep it up.

 Respond  
[Plornt]   -  Mar 30, 2011

Oooh nice, I think my next project (tonight) will probably be a game on canvas although it might be laggy as hell. Plus sunslayer Firefox has a console. But yeah Ive made a few ammendments the log shouldnt have even been in there but I commented it out incase I need to debug somthing quickly :P

I also changed the delete keyword thing, I use getters and setters usually so thats why I made it in to a function. But yeah its not needed so I changed it ^^

Thanks for the comments :)

 Respond  
Hawkee   -  Mar 29, 2011

Here's something I found that has a similar effect: http://www.ponticstar.com/projects/burning-words/

 Respond  
Hawkee   -  Mar 29, 2011

@sunslayer, that's not the problem. The problem is that he defined "delete" as a variable when it's a reserved word on Safari and Firefox. Changing it to another word in both places fixes the problem. In fact it isn't even needed because the "markDelete" variable can be used instead.

 Respond  
sunslayer   -  Mar 29, 2011

@Hawkee change

console.log(this.originX,this.originY,this.originX,0,this.step);

to

if (navigator.appName == 'Microsoft Internet Explorer')             console.log(this.originX,this.originY,this.originX,0,this.step);

making more use of jQuery would eliminate the need for browser checking

 Respond  
Hawkee   -  Mar 29, 2011

This is pretty neat, but it would be nice if it worked on Safari and Firefox 3.6.

 Respond  
[Plornt]   -  Mar 29, 2011

http://i.imgur.com/FaSJC.png

Changed the way it makes the fire, Its circles with minusing size and opacity every screen wipe.

 Respond  
Sorasyn   -  Mar 28, 2011

It works on Google Chrome. As for the hosting situation I'm sure you can find a free hosting site for your snippets. I used one for my Mouse Applet and as far as I know it's still up. (Although, admittingly I haven't checked in on it in several weeks now.)

 Respond  
F*U*R*B*Y*   -  Mar 28, 2011

just tried it, seems ok

would say about you can constantly click on Start Animation again. and it starts it whilst the current animation is going still....

 Respond  
[Plornt]   -  Mar 28, 2011

I would but my hosting situation is messed up at the moment, Also I just xconfirmed with others and the demo is online. Im not too sure if ti works under other browsers other than ff4 rc but yeah thanks for commenting, I have to go bed now since I have work in the morning :p

 Respond  
Hawkee   -  Mar 28, 2011

The demo didn't work. I tried it on both Safari and Firefox. You should host it somewhere permanent so it stays online always.

 Respond  
Are you sure you want to unfollow this person?
Are you sure you want to delete this?
Click "Unsubscribe" to stop receiving notices pertaining to this post.
Click "Subscribe" to resume notices pertaining to this post.