Improving performance of particles in canvas












4















I've been trying to recreate this Project in canvas and Javascript. I wasn't able to decipher the original code so I did it from scratch. The difference is that my projects starts to lag at about 2500 particles while the project above works with 30 000.



I'll paste my entire code below but these are the relevant parts:



var particleContainer = 
var distance = 10


for(let i = 0; i< square.height/distance; i++){
for(let j = 0; j< square.height/distance; j++){
particleContainer.push( new Particle(square.x + i*distance,square.y + j*distance) )
}
}

if( c < 90 ){
i.xVelocity = a/c * -20
i.yVelocity = b/c * -20
}else if(90 < c && c < 95){
i.xVelocity = a/c * -1
i.yVelocity = b/c * -1
}else if(c2 !== 0){
i.xVelocity =( a2/c2 )
i.yVelocity = (b2/c2 )
}



  • (c -> distance between mouse and particle)


I'm creating a new Particle every 'distance' pixels of my square and pushing all of them into an array. when My mouse is to close to one of them the particle will start moving away from the mouse until it is 90-95px away from the Mouse.



30 000 pixels seems to work in a similar fashion judging from this line



  for ( i = 0; i < NUM_PARTICLES; i++ ) {

p = Object.create( particle );
p.x = p.ox = MARGIN + SPACING * ( i % COLS );
p.y = p.oy = MARGIN + SPACING * Math.floor( i / COLS );

list[i] = p;
}


but that project doesn't run into the same case of performance Issues as I.



my full code for reference, (html is just a canvas):



var canvas = document.querySelector("canvas")
var c = canvas.getContext('2d')




function getMousePos(canvas, evt) {
// var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX,
y: evt.clientY
};
}

document.addEventListener('mousemove', function(evt) {
var mousePos = getMousePos(canvas, evt);
mouse.x= mousePos.x;
mouse.y= mousePos.y;
}, false);

var mouse = {
x:0,
y:0
}

function Particle(x,y){
this.x = x;
this.y = y;
this.xFixed = x;
this.yFixed = y;
this.radius = 1
this.xVelocity = 0
this.yVelocity = 0
this.color = 'white'
}

Particle.prototype.draw = function(){
c.save()
c.beginPath()
c.arc(this.x, this.y, this.radius,0,Math.PI*2,false)
c.fillStyle = this.color
c.fill()
}

Particle.prototype.update = function(){
this.draw()
this.x += this.xVelocity
this.y += this.yVelocity
}

var square = {
x: 500,
y: 150,
height: 500,
width: 500,
color: 'white'
}

var particleContainer =
var distance = 10


for(let i = 0; i< square.height/distance; i++){
for(let j = 0; j< square.height/distance; j++){
particleContainer.push( new Particle(square.x + i*distance,square.y + j*distance) )
}

}





function animate(){
requestAnimationFrame(animate);
c.clearRect(0,0,window.innerWidth,window.innerHeight)

canvas.width = window.innerWidth
canvas.height = window.innerHeight

for(i of particleContainer){
let a = mouse.x - i.x
let b = mouse.y - i.y
let c = Math.sqrt(Math.pow(b,2) + Math.pow(a,2))

let a2 = i.xFixed - i.x
let b2 = i.yFixed - i.y
let c2 = Math.sqrt(Math.pow(b2,2) + Math.pow(a2,2))

if( c < 90 ){
i.xVelocity = a/c * -20
i.yVelocity = b/c * -20
}else if(90 < c && c < 95){
i.xVelocity = a/c * -1
i.yVelocity = b/c * -1
}else if(c2 !== 0){
i.xVelocity =( a2/c2 )
i.yVelocity = (b2/c2 )
}


}

for(i of particleContainer){
i.update()
}
}

animate()









share|improve this question





























    4















    I've been trying to recreate this Project in canvas and Javascript. I wasn't able to decipher the original code so I did it from scratch. The difference is that my projects starts to lag at about 2500 particles while the project above works with 30 000.



    I'll paste my entire code below but these are the relevant parts:



    var particleContainer = 
    var distance = 10


    for(let i = 0; i< square.height/distance; i++){
    for(let j = 0; j< square.height/distance; j++){
    particleContainer.push( new Particle(square.x + i*distance,square.y + j*distance) )
    }
    }

    if( c < 90 ){
    i.xVelocity = a/c * -20
    i.yVelocity = b/c * -20
    }else if(90 < c && c < 95){
    i.xVelocity = a/c * -1
    i.yVelocity = b/c * -1
    }else if(c2 !== 0){
    i.xVelocity =( a2/c2 )
    i.yVelocity = (b2/c2 )
    }



    • (c -> distance between mouse and particle)


    I'm creating a new Particle every 'distance' pixels of my square and pushing all of them into an array. when My mouse is to close to one of them the particle will start moving away from the mouse until it is 90-95px away from the Mouse.



    30 000 pixels seems to work in a similar fashion judging from this line



      for ( i = 0; i < NUM_PARTICLES; i++ ) {

    p = Object.create( particle );
    p.x = p.ox = MARGIN + SPACING * ( i % COLS );
    p.y = p.oy = MARGIN + SPACING * Math.floor( i / COLS );

    list[i] = p;
    }


    but that project doesn't run into the same case of performance Issues as I.



    my full code for reference, (html is just a canvas):



    var canvas = document.querySelector("canvas")
    var c = canvas.getContext('2d')




    function getMousePos(canvas, evt) {
    // var rect = canvas.getBoundingClientRect();
    return {
    x: evt.clientX,
    y: evt.clientY
    };
    }

    document.addEventListener('mousemove', function(evt) {
    var mousePos = getMousePos(canvas, evt);
    mouse.x= mousePos.x;
    mouse.y= mousePos.y;
    }, false);

    var mouse = {
    x:0,
    y:0
    }

    function Particle(x,y){
    this.x = x;
    this.y = y;
    this.xFixed = x;
    this.yFixed = y;
    this.radius = 1
    this.xVelocity = 0
    this.yVelocity = 0
    this.color = 'white'
    }

    Particle.prototype.draw = function(){
    c.save()
    c.beginPath()
    c.arc(this.x, this.y, this.radius,0,Math.PI*2,false)
    c.fillStyle = this.color
    c.fill()
    }

    Particle.prototype.update = function(){
    this.draw()
    this.x += this.xVelocity
    this.y += this.yVelocity
    }

    var square = {
    x: 500,
    y: 150,
    height: 500,
    width: 500,
    color: 'white'
    }

    var particleContainer =
    var distance = 10


    for(let i = 0; i< square.height/distance; i++){
    for(let j = 0; j< square.height/distance; j++){
    particleContainer.push( new Particle(square.x + i*distance,square.y + j*distance) )
    }

    }





    function animate(){
    requestAnimationFrame(animate);
    c.clearRect(0,0,window.innerWidth,window.innerHeight)

    canvas.width = window.innerWidth
    canvas.height = window.innerHeight

    for(i of particleContainer){
    let a = mouse.x - i.x
    let b = mouse.y - i.y
    let c = Math.sqrt(Math.pow(b,2) + Math.pow(a,2))

    let a2 = i.xFixed - i.x
    let b2 = i.yFixed - i.y
    let c2 = Math.sqrt(Math.pow(b2,2) + Math.pow(a2,2))

    if( c < 90 ){
    i.xVelocity = a/c * -20
    i.yVelocity = b/c * -20
    }else if(90 < c && c < 95){
    i.xVelocity = a/c * -1
    i.yVelocity = b/c * -1
    }else if(c2 !== 0){
    i.xVelocity =( a2/c2 )
    i.yVelocity = (b2/c2 )
    }


    }

    for(i of particleContainer){
    i.update()
    }
    }

    animate()









    share|improve this question



























      4












      4








      4


      1






      I've been trying to recreate this Project in canvas and Javascript. I wasn't able to decipher the original code so I did it from scratch. The difference is that my projects starts to lag at about 2500 particles while the project above works with 30 000.



      I'll paste my entire code below but these are the relevant parts:



      var particleContainer = 
      var distance = 10


      for(let i = 0; i< square.height/distance; i++){
      for(let j = 0; j< square.height/distance; j++){
      particleContainer.push( new Particle(square.x + i*distance,square.y + j*distance) )
      }
      }

      if( c < 90 ){
      i.xVelocity = a/c * -20
      i.yVelocity = b/c * -20
      }else if(90 < c && c < 95){
      i.xVelocity = a/c * -1
      i.yVelocity = b/c * -1
      }else if(c2 !== 0){
      i.xVelocity =( a2/c2 )
      i.yVelocity = (b2/c2 )
      }



      • (c -> distance between mouse and particle)


      I'm creating a new Particle every 'distance' pixels of my square and pushing all of them into an array. when My mouse is to close to one of them the particle will start moving away from the mouse until it is 90-95px away from the Mouse.



      30 000 pixels seems to work in a similar fashion judging from this line



        for ( i = 0; i < NUM_PARTICLES; i++ ) {

      p = Object.create( particle );
      p.x = p.ox = MARGIN + SPACING * ( i % COLS );
      p.y = p.oy = MARGIN + SPACING * Math.floor( i / COLS );

      list[i] = p;
      }


      but that project doesn't run into the same case of performance Issues as I.



      my full code for reference, (html is just a canvas):



      var canvas = document.querySelector("canvas")
      var c = canvas.getContext('2d')




      function getMousePos(canvas, evt) {
      // var rect = canvas.getBoundingClientRect();
      return {
      x: evt.clientX,
      y: evt.clientY
      };
      }

      document.addEventListener('mousemove', function(evt) {
      var mousePos = getMousePos(canvas, evt);
      mouse.x= mousePos.x;
      mouse.y= mousePos.y;
      }, false);

      var mouse = {
      x:0,
      y:0
      }

      function Particle(x,y){
      this.x = x;
      this.y = y;
      this.xFixed = x;
      this.yFixed = y;
      this.radius = 1
      this.xVelocity = 0
      this.yVelocity = 0
      this.color = 'white'
      }

      Particle.prototype.draw = function(){
      c.save()
      c.beginPath()
      c.arc(this.x, this.y, this.radius,0,Math.PI*2,false)
      c.fillStyle = this.color
      c.fill()
      }

      Particle.prototype.update = function(){
      this.draw()
      this.x += this.xVelocity
      this.y += this.yVelocity
      }

      var square = {
      x: 500,
      y: 150,
      height: 500,
      width: 500,
      color: 'white'
      }

      var particleContainer =
      var distance = 10


      for(let i = 0; i< square.height/distance; i++){
      for(let j = 0; j< square.height/distance; j++){
      particleContainer.push( new Particle(square.x + i*distance,square.y + j*distance) )
      }

      }





      function animate(){
      requestAnimationFrame(animate);
      c.clearRect(0,0,window.innerWidth,window.innerHeight)

      canvas.width = window.innerWidth
      canvas.height = window.innerHeight

      for(i of particleContainer){
      let a = mouse.x - i.x
      let b = mouse.y - i.y
      let c = Math.sqrt(Math.pow(b,2) + Math.pow(a,2))

      let a2 = i.xFixed - i.x
      let b2 = i.yFixed - i.y
      let c2 = Math.sqrt(Math.pow(b2,2) + Math.pow(a2,2))

      if( c < 90 ){
      i.xVelocity = a/c * -20
      i.yVelocity = b/c * -20
      }else if(90 < c && c < 95){
      i.xVelocity = a/c * -1
      i.yVelocity = b/c * -1
      }else if(c2 !== 0){
      i.xVelocity =( a2/c2 )
      i.yVelocity = (b2/c2 )
      }


      }

      for(i of particleContainer){
      i.update()
      }
      }

      animate()









      share|improve this question
















      I've been trying to recreate this Project in canvas and Javascript. I wasn't able to decipher the original code so I did it from scratch. The difference is that my projects starts to lag at about 2500 particles while the project above works with 30 000.



      I'll paste my entire code below but these are the relevant parts:



      var particleContainer = 
      var distance = 10


      for(let i = 0; i< square.height/distance; i++){
      for(let j = 0; j< square.height/distance; j++){
      particleContainer.push( new Particle(square.x + i*distance,square.y + j*distance) )
      }
      }

      if( c < 90 ){
      i.xVelocity = a/c * -20
      i.yVelocity = b/c * -20
      }else if(90 < c && c < 95){
      i.xVelocity = a/c * -1
      i.yVelocity = b/c * -1
      }else if(c2 !== 0){
      i.xVelocity =( a2/c2 )
      i.yVelocity = (b2/c2 )
      }



      • (c -> distance between mouse and particle)


      I'm creating a new Particle every 'distance' pixels of my square and pushing all of them into an array. when My mouse is to close to one of them the particle will start moving away from the mouse until it is 90-95px away from the Mouse.



      30 000 pixels seems to work in a similar fashion judging from this line



        for ( i = 0; i < NUM_PARTICLES; i++ ) {

      p = Object.create( particle );
      p.x = p.ox = MARGIN + SPACING * ( i % COLS );
      p.y = p.oy = MARGIN + SPACING * Math.floor( i / COLS );

      list[i] = p;
      }


      but that project doesn't run into the same case of performance Issues as I.



      my full code for reference, (html is just a canvas):



      var canvas = document.querySelector("canvas")
      var c = canvas.getContext('2d')




      function getMousePos(canvas, evt) {
      // var rect = canvas.getBoundingClientRect();
      return {
      x: evt.clientX,
      y: evt.clientY
      };
      }

      document.addEventListener('mousemove', function(evt) {
      var mousePos = getMousePos(canvas, evt);
      mouse.x= mousePos.x;
      mouse.y= mousePos.y;
      }, false);

      var mouse = {
      x:0,
      y:0
      }

      function Particle(x,y){
      this.x = x;
      this.y = y;
      this.xFixed = x;
      this.yFixed = y;
      this.radius = 1
      this.xVelocity = 0
      this.yVelocity = 0
      this.color = 'white'
      }

      Particle.prototype.draw = function(){
      c.save()
      c.beginPath()
      c.arc(this.x, this.y, this.radius,0,Math.PI*2,false)
      c.fillStyle = this.color
      c.fill()
      }

      Particle.prototype.update = function(){
      this.draw()
      this.x += this.xVelocity
      this.y += this.yVelocity
      }

      var square = {
      x: 500,
      y: 150,
      height: 500,
      width: 500,
      color: 'white'
      }

      var particleContainer =
      var distance = 10


      for(let i = 0; i< square.height/distance; i++){
      for(let j = 0; j< square.height/distance; j++){
      particleContainer.push( new Particle(square.x + i*distance,square.y + j*distance) )
      }

      }





      function animate(){
      requestAnimationFrame(animate);
      c.clearRect(0,0,window.innerWidth,window.innerHeight)

      canvas.width = window.innerWidth
      canvas.height = window.innerHeight

      for(i of particleContainer){
      let a = mouse.x - i.x
      let b = mouse.y - i.y
      let c = Math.sqrt(Math.pow(b,2) + Math.pow(a,2))

      let a2 = i.xFixed - i.x
      let b2 = i.yFixed - i.y
      let c2 = Math.sqrt(Math.pow(b2,2) + Math.pow(a2,2))

      if( c < 90 ){
      i.xVelocity = a/c * -20
      i.yVelocity = b/c * -20
      }else if(90 < c && c < 95){
      i.xVelocity = a/c * -1
      i.yVelocity = b/c * -1
      }else if(c2 !== 0){
      i.xVelocity =( a2/c2 )
      i.yVelocity = (b2/c2 )
      }


      }

      for(i of particleContainer){
      i.update()
      }
      }

      animate()






      javascript canvas html5-canvas






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 24 '18 at 7:44









      marc_s

      573k12811071255




      573k12811071255










      asked Nov 22 '18 at 8:56









      cubefoxcubefox

      918




      918
























          2 Answers
          2






          active

          oldest

          votes


















          1














          To get better rendering you need to add render objects to the same path. Once the path is created then you can draw them in one call to ctx.fill



          Try to limit accessing innerWidth and innerHeight as they are very slow DOM objects that may cause reflows just by accessing them.



          Further improvements can be made by using object pools and preallocation but that is beyond the scope of a single answer.



          Make the following changes to your animate function.



          var W = 1, H = 1;
          function animate() {
          requestAnimationFrame(animate);
          c.clearRect(0 ,0, W, H)
          if (H !== innerHeight || W !== innerWidth) {
          W = canvas.width = innerWidth;
          H = canvas.height = innerHeight;
          }
          c.beginPath(); // start a new path
          c.fillStyle = "white";
          for (i of particleContainer) { // update and draw all particles in one pass
          const a = mouse.x - i.x, b = mouse.y - i.y
          const c = (b * b + a * a) ** 0.5;
          const a2 = i.xFixed - i.x, b2 = i.yFixed - i.y
          const c2 = (b2 * b2 + a2 * a2) ** 0.5;
          if( c < 90 ){
          i.x += a/c * -20
          i.y += b/c * -20
          }else if(90 < c && c < 95){
          i.x += a/c * -1
          i.y += b/c * -1
          }else if(c2 !== 0){
          i.x +=( a2/c2 )
          i.y += (b2/c2 )
          }
          c.rect(i.x, i.y, 1,1);
          }
          c.fill(); // path complete render it.
          //for(i of particleContainer){ // no longer needed
          // i.update()
          //}
          }





          share|improve this answer































            1














            Learn to use the Performance tab in dev tools and you can see which functions are taking the most time. In this case I think you’ll see that it’s ctx.fill. The example you posted is writing pixels into an ImageData buffer which will be much faster than drawing and filling arcs. There are a lot of other small optimisations in the example but that’s going to be the most important one, drawing is usually much slower than updating.






            share|improve this answer























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53427122%2fimproving-performance-of-particles-in-canvas%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              1














              To get better rendering you need to add render objects to the same path. Once the path is created then you can draw them in one call to ctx.fill



              Try to limit accessing innerWidth and innerHeight as they are very slow DOM objects that may cause reflows just by accessing them.



              Further improvements can be made by using object pools and preallocation but that is beyond the scope of a single answer.



              Make the following changes to your animate function.



              var W = 1, H = 1;
              function animate() {
              requestAnimationFrame(animate);
              c.clearRect(0 ,0, W, H)
              if (H !== innerHeight || W !== innerWidth) {
              W = canvas.width = innerWidth;
              H = canvas.height = innerHeight;
              }
              c.beginPath(); // start a new path
              c.fillStyle = "white";
              for (i of particleContainer) { // update and draw all particles in one pass
              const a = mouse.x - i.x, b = mouse.y - i.y
              const c = (b * b + a * a) ** 0.5;
              const a2 = i.xFixed - i.x, b2 = i.yFixed - i.y
              const c2 = (b2 * b2 + a2 * a2) ** 0.5;
              if( c < 90 ){
              i.x += a/c * -20
              i.y += b/c * -20
              }else if(90 < c && c < 95){
              i.x += a/c * -1
              i.y += b/c * -1
              }else if(c2 !== 0){
              i.x +=( a2/c2 )
              i.y += (b2/c2 )
              }
              c.rect(i.x, i.y, 1,1);
              }
              c.fill(); // path complete render it.
              //for(i of particleContainer){ // no longer needed
              // i.update()
              //}
              }





              share|improve this answer




























                1














                To get better rendering you need to add render objects to the same path. Once the path is created then you can draw them in one call to ctx.fill



                Try to limit accessing innerWidth and innerHeight as they are very slow DOM objects that may cause reflows just by accessing them.



                Further improvements can be made by using object pools and preallocation but that is beyond the scope of a single answer.



                Make the following changes to your animate function.



                var W = 1, H = 1;
                function animate() {
                requestAnimationFrame(animate);
                c.clearRect(0 ,0, W, H)
                if (H !== innerHeight || W !== innerWidth) {
                W = canvas.width = innerWidth;
                H = canvas.height = innerHeight;
                }
                c.beginPath(); // start a new path
                c.fillStyle = "white";
                for (i of particleContainer) { // update and draw all particles in one pass
                const a = mouse.x - i.x, b = mouse.y - i.y
                const c = (b * b + a * a) ** 0.5;
                const a2 = i.xFixed - i.x, b2 = i.yFixed - i.y
                const c2 = (b2 * b2 + a2 * a2) ** 0.5;
                if( c < 90 ){
                i.x += a/c * -20
                i.y += b/c * -20
                }else if(90 < c && c < 95){
                i.x += a/c * -1
                i.y += b/c * -1
                }else if(c2 !== 0){
                i.x +=( a2/c2 )
                i.y += (b2/c2 )
                }
                c.rect(i.x, i.y, 1,1);
                }
                c.fill(); // path complete render it.
                //for(i of particleContainer){ // no longer needed
                // i.update()
                //}
                }





                share|improve this answer


























                  1












                  1








                  1







                  To get better rendering you need to add render objects to the same path. Once the path is created then you can draw them in one call to ctx.fill



                  Try to limit accessing innerWidth and innerHeight as they are very slow DOM objects that may cause reflows just by accessing them.



                  Further improvements can be made by using object pools and preallocation but that is beyond the scope of a single answer.



                  Make the following changes to your animate function.



                  var W = 1, H = 1;
                  function animate() {
                  requestAnimationFrame(animate);
                  c.clearRect(0 ,0, W, H)
                  if (H !== innerHeight || W !== innerWidth) {
                  W = canvas.width = innerWidth;
                  H = canvas.height = innerHeight;
                  }
                  c.beginPath(); // start a new path
                  c.fillStyle = "white";
                  for (i of particleContainer) { // update and draw all particles in one pass
                  const a = mouse.x - i.x, b = mouse.y - i.y
                  const c = (b * b + a * a) ** 0.5;
                  const a2 = i.xFixed - i.x, b2 = i.yFixed - i.y
                  const c2 = (b2 * b2 + a2 * a2) ** 0.5;
                  if( c < 90 ){
                  i.x += a/c * -20
                  i.y += b/c * -20
                  }else if(90 < c && c < 95){
                  i.x += a/c * -1
                  i.y += b/c * -1
                  }else if(c2 !== 0){
                  i.x +=( a2/c2 )
                  i.y += (b2/c2 )
                  }
                  c.rect(i.x, i.y, 1,1);
                  }
                  c.fill(); // path complete render it.
                  //for(i of particleContainer){ // no longer needed
                  // i.update()
                  //}
                  }





                  share|improve this answer













                  To get better rendering you need to add render objects to the same path. Once the path is created then you can draw them in one call to ctx.fill



                  Try to limit accessing innerWidth and innerHeight as they are very slow DOM objects that may cause reflows just by accessing them.



                  Further improvements can be made by using object pools and preallocation but that is beyond the scope of a single answer.



                  Make the following changes to your animate function.



                  var W = 1, H = 1;
                  function animate() {
                  requestAnimationFrame(animate);
                  c.clearRect(0 ,0, W, H)
                  if (H !== innerHeight || W !== innerWidth) {
                  W = canvas.width = innerWidth;
                  H = canvas.height = innerHeight;
                  }
                  c.beginPath(); // start a new path
                  c.fillStyle = "white";
                  for (i of particleContainer) { // update and draw all particles in one pass
                  const a = mouse.x - i.x, b = mouse.y - i.y
                  const c = (b * b + a * a) ** 0.5;
                  const a2 = i.xFixed - i.x, b2 = i.yFixed - i.y
                  const c2 = (b2 * b2 + a2 * a2) ** 0.5;
                  if( c < 90 ){
                  i.x += a/c * -20
                  i.y += b/c * -20
                  }else if(90 < c && c < 95){
                  i.x += a/c * -1
                  i.y += b/c * -1
                  }else if(c2 !== 0){
                  i.x +=( a2/c2 )
                  i.y += (b2/c2 )
                  }
                  c.rect(i.x, i.y, 1,1);
                  }
                  c.fill(); // path complete render it.
                  //for(i of particleContainer){ // no longer needed
                  // i.update()
                  //}
                  }






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 22 '18 at 11:20









                  Blindman67Blindman67

                  26.5k52762




                  26.5k52762

























                      1














                      Learn to use the Performance tab in dev tools and you can see which functions are taking the most time. In this case I think you’ll see that it’s ctx.fill. The example you posted is writing pixels into an ImageData buffer which will be much faster than drawing and filling arcs. There are a lot of other small optimisations in the example but that’s going to be the most important one, drawing is usually much slower than updating.






                      share|improve this answer




























                        1














                        Learn to use the Performance tab in dev tools and you can see which functions are taking the most time. In this case I think you’ll see that it’s ctx.fill. The example you posted is writing pixels into an ImageData buffer which will be much faster than drawing and filling arcs. There are a lot of other small optimisations in the example but that’s going to be the most important one, drawing is usually much slower than updating.






                        share|improve this answer


























                          1












                          1








                          1







                          Learn to use the Performance tab in dev tools and you can see which functions are taking the most time. In this case I think you’ll see that it’s ctx.fill. The example you posted is writing pixels into an ImageData buffer which will be much faster than drawing and filling arcs. There are a lot of other small optimisations in the example but that’s going to be the most important one, drawing is usually much slower than updating.






                          share|improve this answer













                          Learn to use the Performance tab in dev tools and you can see which functions are taking the most time. In this case I think you’ll see that it’s ctx.fill. The example you posted is writing pixels into an ImageData buffer which will be much faster than drawing and filling arcs. There are a lot of other small optimisations in the example but that’s going to be the most important one, drawing is usually much slower than updating.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 22 '18 at 9:43









                          Ben WestBen West

                          2,7211814




                          2,7211814






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53427122%2fimproving-performance-of-particles-in-canvas%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Wiesbaden

                              Marschland

                              Dieringhausen