Dominique
Dominique

Reputation: 449

Javascript draw canvas memory leak

This script is endlessly taking memory in all the browsers. I can't see why!

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var particles = [], amount = 5;
var x = 100; var y = 100;
var W, H;
var p, gradient;  

//dimensions
if(window.innerHeight){
    W = window.innerWidth, H = window.innerHeight;
}else{
    W = document.documentElement.clientWidth, H = document.documentElement.clientHeight;
}
canvas.width = W, canvas.height = H;


//array voor de meerdere particles
for(var i=0;i<amount;i++){
    particles.push(new create_particle());
}

function create_particle(){
    //random positie op canvas
    this.x = Math.random()*W;
    this.y = Math.random()*H;

    //random snelheid
    this.vx = Math.random()*20-10;
    this.vy = Math.random()*20-10;

    //Random kleur
    var r = Math.random()*255>>0;
    var g = Math.random()*255>>0;
    var b = Math.random()*255>>0;
    this.color = "rgba("+r+", "+g+", "+b+", 0.5)";
    this.radius = Math.random()*20+20;

}

window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       || 
          window.webkitRequestAnimationFrame || 
          window.mozRequestAnimationFrame    || 
          window.oRequestAnimationFrame      || 
          window.msRequestAnimationFrame     || 
          function( callback ){
            window.setTimeout(callback, 1000 / 60);
          };
})();

function draw(){
    canvas.width = canvas.width;
    canvas.height = canvas.height;
    //achtergrond tekenen
    //ctx.globalCompositeOperation = "source-over";
    //ctx.fillStyle = "rgba(0,0,0,0.5)";
    ctx.fillRect(0, 0, W, H);
    //ctx.globalCompositeOperation = "lighter";

    //teken cirkel
    for(var t=0; t<particles.length;t++){
        p = particles[t];

        //gradient
        gradient = ctx.createRadialGradient(p.x,p.y,0,p.x,p.y,p.radius);
        gradient.addColorStop(0,"white");
        gradient.addColorStop(0.4,"white");
        gradient.addColorStop(0.4,p.color);
        gradient.addColorStop(1,"black");
        ctx.beginPath();
        ctx.fillStyle = gradient;
        ctx.arc(p.x,p.y,p.radius,Math.PI*2,false)
        ctx.fill();

        //beweeg
        p.x+=p.vx;
        p.y+=p.vy;

        //canvas boundery detect
        if(p.x < -50)p.x = W+50;
        if(p.y < -50)p.y=H+50;
        if(p.x > W+50)p.x = -50;
        if(p.y > H+50)p.y = -50;
    }
}

(function animloop(){
    canvas.width = canvas.width;
    canvas.height = canvas.height;
    requestAnimFrame(animloop);
    draw();
})();


//resize?
function resizeCanvas(){ 
    canvas.height = W; 
    canvas.width = H;
    ctx.fillRect(0, 0, W, H);
}
if(window.addEventListener){
     window.addEventListener('resize', resizeCanvas, false);
}else{
     window.attachEvent('resize', resizeCanvas);
}

I tried to change some code around (this is also final version) but still it leaks. If you use this script and watch 'taskmanager' or in-browser's memory check you see that it slowly and constantly eats memory.

EDIT: after adding in the canvas.height solution and moving some declaring's around, the script still leaks! I must say that it looks like Firefox leaks harder then Chrome!

Upvotes: 5

Views: 3841

Answers (3)

Mouseroot
Mouseroot

Reputation: 1064

my guess is your create_particle function could be leaking but im not sure as how, one idea would be to create an interal object instead of using this

function create_particle(){
  return {
    x: Math.random()*W,
    y: Math.random()*H,
    vx: Math.random()*20-10,
    vy: Math.random()*20-10,
    r: Math.random()*255>>0,
    g: Math.random()*255>>0,
    b: Math.random()*255>>0,
    color: "rgba("+r+", "+g+", "+b+", 0.5)",
    radius: Math.random()*20+20,
  };
}

Im not sure if this is the issue, but it seems to be the only thing I can really think of that kinda looks odd,

Upvotes: 0

Sir
Sir

Reputation: 8277

You have:

   canvas.width = canvas.width;
    canvas.height = canvas.height;

I'm guessing this does the same as clearRect... but to be sure try this too:

function draw(){

   ctx.clearRect ( 0 , 0 , canvas.width , canvas.height );

   /* draw */
}

See if any thing changes.

Upvotes: 2

gabitzish
gabitzish

Reputation: 9691

Try cleaning the canvas before starting another set of drawing. You can clear it by setting it's width and height again.

Here is some orientative code:

function draw() {
   canvas.width = canvas.width;
   canvas.height = canvas.height;

   /* draw */
}

Upvotes: 1

Related Questions