admin管理员组

文章数量:1431420

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!

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!

Share Improve this question edited Jan 20, 2013 at 5:57 Sir 8,27717 gold badges88 silver badges154 bronze badges asked Aug 28, 2012 at 12:10 DominiqueDominique 4492 gold badges6 silver badges15 bronze badges 5
  • 1 Don't use task manager. Use Firefox and about:memory tab, so you get accurate reports how memory is spent. – Mikko Ohtamaa Commented Aug 28, 2012 at 12:19
  • was just a reference because even there, it was more than visible.. but thanks for the tip :) – Dominique Commented Aug 28, 2012 at 12:30
  • Hi. Did you find an answer except "there is a memory leak in gradient" ? – Denys Séguret Commented Aug 29, 2012 at 11:56
  • no, i haven't got the solution yet :( – Dominique Commented Sep 1, 2012 at 13:24
  • createRadialGradient has a memory leak for me too, in Firefox 77.0b9 but not in Chrome or Edge. All Win 7. – Denis Howe Commented Dec 21, 2019 at 12:07
Add a ment  | 

3 Answers 3

Reset to default 2

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.

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 */
}

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,

本文标签: Javascript draw canvas memory leakStack Overflow