HTML5 Canvas "Fireworks"

By [Plornt] on Mar 25, 2011

I coded this as a small learning exercise for myself, not attempting to make any shortening to the code since Im still fairly new to javascript. I know alot of places I could of optimised (Especially the stupid array method I used to create ball objects - imo should of just made a class or somthing liek it if javascript has that?)

But yeah this uses HTML5 canvas to draw exploding "fireworks". Pretty cool to look at, also transparent so you can add a webpage in an iframe under it and it will animate on top >.<. Experimented with that - Made it stop the animation a few times :(

Click to create fireworks

DEMO: http://90.200.78.182/html5/shoot.html

(Demo link goes down when I go offline)

Credits:
vw function - Cant remember who but I certainly didnt code it, found it in my old files.

Path finding along line from some random flash forum of which I accidentally closed the tab of -.- it was converted eversoslightly to javascript by me >.<

http://paulirish.com/2009/random-hex-color-code-snippets/ - Random Hex code

Update -

  • Added Gravity
  • Added fading
  • Made them lines rather than balls
  • Added auto fire option which continuously fires fireworrks by how many times you click.
  • Part of my optimisation:
    • Added Idle time checker
    • Deleted particles from array rather than just made them not show up.
<!DOCTYPE html>
<html>
  <head>
    <title>Canvas Testing Zone</title><script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script>
    var height;
    var auto;
    var width;
    var animObj = new Array();
    var go;
    function vw() {
      if( typeof( window.innerWidth ) == 'number' ) {
        width = window.innerWidth;
        height = window.innerHeight;
      } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
        width = document.documentElement.clientWidth;
        height = document.documentElement.clientHeight;
      } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
        width = document.body.clientWidth;
        height = document.body.clientHeight;
      }
    }
    window.onload = init;
    function init () {
        var canvas = document.getElementById("fireworks");
        var context = canvas.getContext("2d");
        vw(); canvas.width =  width;
        canvas.height =  height;
        clearTimeout(go);
        drawnext(canvas,context);
    }
    function flashbang (col) {
        $('#white').stop();
        $('#white').css('backgroundColor',""+col+"");
        $('#white').fadeTo(100,0.4, function() {
            $(this).fadeOut(200);
          });
    }
    function drawl (e,canvas) {
    var stX = Math.floor(Math.random()* canvas.width +1);
    var stY = canvas.height;
    var spee = rand(10,40);
    var endX = (e.clientX-canvas.offsetLeft);
    var endY = (e.clientY-canvas.offsetTop);
        addAnim('ball','objBall',endX,endY,1,spee,stX,stY,rrgba(1));
    if (rand(30,60) <= 45) addAnim('ball','objBall',(endX + 1),endY,1,spee,stX,stY,rrgba(1));
    }
    function addAnim (name,callback,endX,endY,step,speed,x,y,colour) {
        var b = new Array (name,callback,endX,endY,step,speed,0,x,y,colour,1,1);
        animObj.push(b);
        if (idlerender == "off") {
            idlerender = "on";
            var canvas = document.getElementById("fireworks");
            var context = canvas.getContext("2d");
            drawnext(canvas,context);
            console.log("Restarted screen animation");
        }
    }
    function rrgba (alpha) { var rint = (Math.floor(0xffffff * Math.random()) + 1); return 'rgba(' + (rint >> 16) + ',' + (rint >> 8 & 255) + ',' + (rint & 255); }
    function len (v) { return (v.length + 1); }
    function rand (l,h) { var rand = Math.floor((Math.random() * h) + 1); while (rand < l) rand = Math.floor((Math.random() * h) + 1);  return rand; }

    function objBall(endX,endY,t,canvas,context,update,stX,stY) {
        animObj[update][4] += animObj[update][5];
        //console.log("x: "+endX+" y: "+endY+" step: "+t+" posInArray: "+update);
        var x3 = endX - stX; 
        var y3 = endY - stY;
        var length = Math.sqrt(((x3 * x3) + (y3 * y3)));
        x3 /= length;
        y3 /= length;
        x3 *= t;
        y3 *= t;
        x3 += Math.floor(stX);
        y3 += stY;
        animObj[update][12] = animObj[update][10];
        animObj[update][10] += ((animObj[update][0] == "e") ? 0.04 : 0.006) * t;
        y3 += Math.floor(animObj[update][10]);
        if (((x3 <= Math.floor(Math.random()*100) || y3 <= Math.floor(Math.random()*100)) || (x3 >=  (canvas.width - Math.floor(Math.random()*100)) || y3 >= (canvas.height + 1))) && animObj[update][0] == "ball") {
            animObj[update][6] = 1;
            //flashbang(animObj[update][9]+',1)');
            for (var i=0;i<=100;i++) {
                addAnim('e','objBall',(x3 + (rand(1,100) - 50)),(y3 + (rand(1,100) - 50)),1,rand(1,5),x3,y3,animObj[update][9]);
            }
            //Auto Create
            if (auto == 1) addAnim('ball','objBall',(Math.floor(Math.random()*canvas.width)),(Math.floor(Math.random()*canvas.height)),1,rand(10,40),Math.floor(Math.random()* canvas.width +1),canvas.height,rrgba(1));
        }
        else if (((x3 <= 0 || y3 <= 0) || (x3 >= (canvas.width + 1) || y3 >= (canvas.height + 1)))  && animObj[update][0] == "e") {
            animObj[update][6] = 1;
        }
        else {
            try {

            context.beginPath();
            var x4 = endX - stX; 
            var y4 = endY - stY;
            var length = Math.sqrt(((x4 * x4) + (y4 * y4)));
            x4 /= length;
            y4 /= length;
            x4 *= (t - animObj[update][5]);
            y4 *= (t - animObj[update][5]);
            x4 += Math.floor(stX);
            y4 += stY;
            y4 += Math.floor(animObj[update][10]);
            context.moveTo(x3, y3);
            context.lineTo(x4, y4);
            context.closePath();
            if (animObj[update][0] == "e") animObj[update][11] -= 0.02;
            context.strokeStyle = ((animObj[update][0] == "e") ? animObj[update][9]+','+((animObj[update][11] <= 0) ? 0 : animObj[update][11])+')' : animObj[update][9]+',1)');

context.stroke();
            }
            catch (err) {
            //Still havent figured out the error but atleast doing this stops it from crashing
            //  console.log(err);
            //  console.log(x3 + ' ' + y3 + ' ' + endX + ' ' + endY + ' ' + stX + ' ' + stY + ' ' + update + ' ' + t + ' ' + length);
            }
        }
    }
    var idlerender;
    var frames=0;
    function drawnext (canvas,context) {
    frames + 1;
        context.clearRect(0,0,canvas.width, canvas.height); 
        //fix array 

            for(var i=0; i < animObj.length; i++) { 
                if (animObj[i][6] == 1 || animObj[i][11] <= 0) { animObj.splice(i,1); i--; }
            }
            var len = animObj.length;
            for(var i=0; i < len; i++) {    
                if (animObj[i][6] != 1) {
                    objBall.call(this,animObj[i][2],animObj[i][3],animObj[i][4],canvas,context,i,animObj[i][7],animObj[i][8],animObj[i][9]);
                }
            }
            frames++;
         if (frames == 500) { if (len == 0) { idlerender = "off"; console.log("Seems to be idle"); } frames = 0; }
        setTimeout(function () { drawnext(canvas,context); },10);
    }

    </script>
  </head><body bgcolor='black' style='background-image: url("http://www.free-high-resolution-photos.com/public/Fotografie/foto/0705200921.41.11-----Landscape_picture.jpg");background-size:100%;'> 
<a style='color:#1D203D;position:relative;z-index:4' href='javascript:var auto = 1;void(0);'>Click here to auto fire</a> - <a style='color:#1D203D;position:relative;z-index:4' href='javascript:if (next) { clearTimeout(next); } animObj=new Array();init();void(0);'>Click here to reset</a> 

  <div id='white' style='position:absolute;left:0;top:0;z-index:2;width:100%;height:100%;background-color:white;display:none;'></div>
 <canvas style='position:absolute;left:0;top:0;z-index:3;' id="fireworks" onclick='drawl(event,this);' width="100%" height="100%">You dont have canvas</canvas>
  </body>
</html>

Comments

Sign in to comment.
sunslayer   -  Mar 27, 2011

from reading the code it looks like it clears the obj arrays and timers

 Respond  
Sorasyn   -  Mar 27, 2011

What's to reset? XD

 Respond  
sunslayer   -  Mar 27, 2011

the reset button doesn't seem to do anything, but nice job

 Respond  
[Plornt]   -  Mar 26, 2011

Thanks :P

I added a small idle time checker as it spikes madly if just left alone, if I can figure out if its the code or generally canvas's then ill fix it proper.

When running the animation it takes 99 CPU wheras when idle it takes less than 2 :)

Ok I tried adding somthing to the idle checker and I fucked it up -.-

 Respond  
Hawkee   -  Mar 26, 2011

Much better, it's running smooth now.

 Respond  
[Plornt]   -  Mar 26, 2011

Ok got them looking pretty much how I want them, time to optimise I guess?

 Respond  
[Plornt]   -  Mar 26, 2011

Fixed the demo up I think... Its a tad slow since I slowed it down so I could debug without crashing my browser with the console logs ^^

 Respond  
Hawkee   -  Mar 26, 2011

The demo seems to run a bit slow on Safari here. On a side note, maybe I should add an HTML5 section to the site.

 Respond  
[Plornt]   -  Mar 26, 2011

I probably shouldnt edit the demo live >.>

Since now its fairly different from the one on here but I dont want to put it on here since its not working properly :/

 Respond  
[Plornt]   -  Mar 25, 2011

Added a sky bg to the demo >.<

Thanks :P

 Respond  
Sorasyn   -  Mar 25, 2011

Very cool. Could use a darker background since I don't think they shoot fireworks during the day or on white pages. XD Other then that looks nice.

 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.