0

I have a particle animation written in JavaScript using Canvas. What i'm trying to do is to change the canvas drawing values, specifically radMax and radMin. I have written the code here for you to see: https://jsfiddle.net/u3wwxg58/

What happens now, is that when I call function f(), new particles are added with the right radMax and radMin values, instead of updating the current "drawing" with the new radMax and radMin values. Basically, what i'm trying to do is to simply make my sphere / animation larger when function f() is called.

My code for drawParticle()

var cvs = document.createElement('canvas'),
context = cvs.getContext('2d');
document.body.appendChild(cvs);

var numDots = 500,
        n = numDots,
        currDot,
        maxRad = 100,
    minRad = 90,
    radDiff = maxRad-minRad,
    dots = [],
    PI = Math.PI,
    centerPt = {x:0, y:0};

    resizeHandler();
    window.onresize = resizeHandler;

    while(n--){
        currDot = {};
        currDot.radius = minRad+Math.random()*radDiff;
        currDot.radiusV = 10+Math.random()*50,
        currDot.radiusVS = (1-Math.random()*2)*0.005,
        currDot.radiusVP = Math.random()*PI,
        currDot.ang = (1-Math.random()*2)*PI;
        currDot.speed = 0;
        //currDot.speed = 1-Math.round(Math.random())*2;
        //currDot.speed = 1;
        currDot.intensityP = Math.random()*PI;
        currDot.intensityS = Math.random()*0.5;
        currDot.intensityO = 64+Math.round(Math.random()*64);
        currDot.intensityV = Math.min(Math.random()*255, currDot.intensityO);
        currDot.intensity = Math.round(Math.random()*255);
        currDot.fillColor = 'rgb('+currDot.intensity+','+currDot.intensity+','+currDot.intensity+')';
        dots.push(currDot);
    }

    function drawPoints(){
        var n = numDots;
        var _centerPt = centerPt,
            _context = context,
            dX = 0,
            dY = 0;

        _context.clearRect(0, 0, cvs.width, cvs.height);

        var radDiff,currDot;
        //draw dots
        while(n--) {
            currDot = dots[n];
            currDot.radiusVP += currDot.radiusVS;
            radDiff = currDot.radius+Math.sin(currDot.radiusVP)*currDot.radiusV;
            dX = _centerPt.x+Math.sin(currDot.ang)*radDiff;
            dY = _centerPt.y+Math.cos(currDot.ang)*radDiff;

            //currDot.ang += currDot.speed;
            currDot.ang += currDot.speed*radDiff/40000;
            currDot.intensityP += currDot.intensityS;
            currDot.intensity = Math.round(currDot.intensityO+Math.sin(currDot.intensityP)*currDot.intensityV);

            //console.log(currDot);
            _context.fillStyle= 'rgb('+currDot.intensity+','+currDot.intensity+','+currDot.intensity+')';
            _context.fillRect(dX, dY, 1, 1);
            console.log('draw dots');

        } //draw dot
        window.requestAnimationFrame(drawPoints);
    }

    function resizeHandler(){
        var box = cvs.getBoundingClientRect();
        var w = box.width;
        var h = box.height;
        cvs.width = w;
        cvs.height = h;
        centerPt.x = Math.round(w/2);
        centerPt.y = Math.round(h/2);
    }

 drawPoints();

and my code for updating the values:

var myi = 0, timex = 20;

         function f() {
         numDots =500+myi*10; maxRad = 300;minRad = 200 ; n=numDots;
         while(n--){
            currDot = {};
            currDot.radius = minRad+Math.random()*radDiff;
            currDot.radiusV = 10+Math.random()*500,
            currDot.radiusVS = (1-Math.random()*2)*0.005,
            currDot.radiusVP = Math.random()*PI,
            currDot.ang = (1-Math.random()*2)*PI;
            currDot.speed = (1-Math.random()*2);
            //currDot.speed = 1-Math.round(Math.random())*2;
            //currDot.speed = 1;
            currDot.intensityP = Math.random()*PI;
            currDot.intensityS = Math.random()*0.05;
            currDot.intensityO = 64+Math.round(Math.random()*64);
            currDot.intensityV = Math.min(Math.random()*255, currDot.intensityO);
            currDot.intensity = Math.round(Math.random()*255);
            currDot.fillColor = 'rgb('+currDot.intensity+','+currDot.intensity+','+currDot.intensity+')';
            dots.push(currDot);
            //setTimeout(function(){n++},1000);
        }
        myi++;
         if( myi < timex ){
        setTimeout( f, 500 );
    }}
    f();

Picture to show what I want to do: https://postimg.org/image/9uhb3jda9/ So left one is before calling function f(), right one is when f() is called.

  • Please simplify your question. This is difficult to follow, what isn't working? – Soviut Oct 29 '16 at 19:22
  • Sorry, I have updated the explanation and also added a picture. Thanks @Soviut – OhNoThatsBad Oct 29 '16 at 19:34
  • Just a side note - when generating random numbers it is usually preferable to use Math.floor instead of Math.round, because the latter [gives a non-uniform distribution](http://stackoverflow.com/a/7377769/6854845). – Jon Oct 29 '16 at 21:04

2 Answers2

0

Function f is adding dots because the statement currDot = {}; creates a new object, and the statement dots.push(currDot); adds it to the array of dots.

If you change it to:

currDot = dots[n];

and remove the push then it will act on the existing dots.

However, that will only work while myi is zero.

Presumably you are intending to increase the number of dots over time. Perhaps what you really want is just to completely replace the existing dots? In which case just stick dots = []; before the while loop and leave the rest as-is.

Jon
  • 361
  • 3
  • 10
0

No point iterating all the particles again just to change the size of the effect. Do it while you are rendering the particles.

From your code add the variable radiusGrowAt and increase each dot radius every time you render it. radiusGrowAt assumes the frame rate is constant and at 60fps

   //just after document.body.appendChild(cvs) where you declare and define
    maxRad = 20,
    minRad = 10,
    radDiff = maxRad-minRad,
    //=================================================================
    radiusGrowAt = 20 / 60, //<<== add this  // grow 20 pixels every 60 frames (one second)
    //=================================================================
    dots = [],
    PI = Math.PI,
    centerPt = {x:0, y:0};       
    ... etc

Then

    //draw dots
    while(n--) {
        currDot = dots[n];
        //=================================================================
        currDot.radius += radiusGrowAt; //<<== add this line
        //=================================================================
        currDot.radiusVP += currDot.radiusVS;
        radDiff = currDot.radius+Math.sin(currDot.radiusVP)*currDot.radiusV;
        ... etc
Blindman67
  • 51,134
  • 11
  • 73
  • 136