1

I can't quite achieve the result I want with the HTML5 canvas animation I'm using.

Basically, what I'm trying to do is to gradually make the "old" stars disappear when they stop moving, otherwise the canvas just gets filled with old stars and becomes all white.

I've tried setting the globalAlpha over time, but I can't quite figure out where to put it, the results I get are comical at best..

Or if anyone has a better idea as how to achieve that effect, I'm all ears. thanks. (original source gotten from: http://www.professorcloud.com/mainsite/canvas-nebula.htm)

Here's a JSFiddle: http://jsfiddle.net/gXLfJ/

And here's the code:

(function ($) {         
        // The canvas element we are drawing into.      
        var $canvas = $('#canvas');
        var $canvas2 = $('#canvas2');
        var $canvas3 = $('#canvas3');           
        var ctx2 = $canvas2[0].getContext('2d');
        var ctx = $canvas[0].getContext('2d');
        var w = $canvas[0].width, h = $canvas[0].height;        
        var img = new Image();  

        // A puff.
        var Puff = function(p) {                
            var opacity,
                sy = (Math.random()*285)>>0,
                sx = (Math.random()*285)>>0;

            this.p = p;

            this.move = function(timeFac) {                     
                p = this.p + 0.3 * timeFac;             
                opacity = (Math.sin(p*0.05)*0.5);                       
                if(opacity <0) {
                    p = opacity = 0;
                    sy = (Math.random()*285)>>0;
                    sx = (Math.random()*285)>>0;
                }                                               
                this.p = p;                                                                         
                ctx.globalAlpha = opacity;                      
                ctx.drawImage($canvas3[0], sy+p, sy+p, 285-(p*2),285-(p*2), 0,0, w, h);                             
            };
        };

        var puffs = [];         
        var sortPuff = function(p1,p2) { return p1.p-p2.p; };   
        puffs.push( new Puff(0) );
        puffs.push( new Puff(20) );
        puffs.push( new Puff(40) );

        var newTime, oldTime = 0, timeFac;

        var loop = function()
        {                               
            newTime = new Date().getTime();             
            if(oldTime === 0 ) {
                oldTime=newTime;
            }
            timeFac = (newTime-oldTime) * 0.1;
            if(timeFac>3) {timeFac=3;}
            oldTime = newTime;                      
            puffs.sort(sortPuff);                           

            for(var i=0;i<puffs.length;i++)
            {
                puffs[i].move(timeFac); 
            }                   
            ctx2.drawImage( $canvas[0] ,0,0,570,570);               
            setTimeout(loop, 10 );              
        };
        // Turns out Chrome is much faster doing bitmap work if the bitmap is in an existing canvas rather
        // than an IMG, VIDEO etc. So draw the big nebula image into canvas3
        var $canvas3 = $('#canvas3');
        var ctx3 = $canvas3[0].getContext('2d');
        $(img).bind('load',null, function() {  ctx3.drawImage(img, 0,0, 570, 570);  loop(); });
        img.src = 'blocks.png';

})(jQuery);
Phil
  • 57
  • 6

1 Answers1

1

I didn't go through all your code so you have to adopt this effect as you need it, but you can make a simple trailing effect (if that's what you're after) by simply filling the canvas with a transparent color.

For example:

/// this will create a "fading" / trailing effect
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';   /// black with high transparency
ctx.fillRect(0, 0, ctx2.canvas.width, ctx2.canvas.height);

ctx.drawImage($canvas3[0], sy+p, sy+p, 285-(p*2),285-(p*2), 0,0, w, h);

(the fill style can be set once outside the loop if you don't use other fill styles instead of each time. Width and height should of course be cached).

Modified fiddle here

  • This is a great way to do it, the only issue is I would like the background to be still visible (in case I put an image for example), this method would render it opaque black. But maybe there's no easy way around this.. – Phil Jan 03 '14 at 15:21
  • 1
    @Phil for that purpose you could look into "particles" such as my [answer here](http://stackoverflow.com/questions/20211855/black-resized-canvas-not-completely-fading-drawings-to-black-over-time/20212980#20212980) which preserve transparency. You can use that with a CSS image background on the canvas element or use two canvases. –  Jan 03 '14 at 20:07