Bodoppels
Bodoppels

Reputation: 406

Draw random coloured circles on canvas

I am trying to create a animation where circles run from right to left. The circles' colours are selected randomly by a function. I have created a fiddle where one circle runs from right to left. Now my function creates a random colour. This function is executed every second and the circle changes its colour every second, instead of a new circle with the random picked colour become created. How can I change it so that it draws a new circle every second on the canvas and doesn't only change the colour of the circle?

This is my function:

function getRandomElement(array) {
  if (array.length == 0) {
    return undefined;
  }
  return array[Math.floor(Math.random() * array.length)];
}

var circles = [
  '#FFFF00',
  '#FF0000',  
  '#0000FF'
];


function drawcircles() {


ctx.beginPath();
      ctx.arc(ballx * 108, canvasHeight / 2, x*5, 0, 2*Math.PI, false);
      ctx.fillStyle = getRandomElement(circles);
      ctx.fill();
ctx.closePath;

}

Upvotes: 3

Views: 1558

Answers (1)

DUUUDE123
DUUUDE123

Reputation: 166

Comments on your question:

You are changing the color of the fillStyle to a random color at each frame. This is the reason why it keeps "changing" color. Set it to the color of the circle:

context.fillStyle = circle.color;
  1. make circles with x, y, diameter, bounciness, speed, and color using an array
  2. draw and update them with requestAnimationFrame (mine is a custom function)

My answer:

I made this just last night, where some circles follow the cursor and "bounce" off the edges of the screen. I tested the code and it works.

I might post a link later, but here is all of the code right now...

<!DOCTYPE html>
<html>
<body>
    <canvas id="canvas"></canvas>
    <script>
        var lastTime = 0;
        function requestMyAnimationFrame(callback, time)
        {
            var t = time || 16;
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, t - (currTime - lastTime));
            var id = window.setTimeout(function(){ callback(currTime + timeToCall); }, timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        }
        var canvas = document.getElementById("canvas");
        var context = canvas.getContext("2d");
        canvas.width = window.innerWidth - 20;
        canvas.height = window.innerHeight - 20;
        canvas.style.width = canvas.width + "px";
        canvas.style.height = canvas.height + "px";
        var circles = [];
        var mouse =
        {
            x: 0,
            y: 0
        }
        function getCoordinates(x, y)
        {
            return "(" + x + ", " + y + ")";
        }
        function getRatio(n, d)
        {
            // prevent division by 0
            if (d === 0 || n === 0)
            {
                return 0;
            }
            else
            {
                return n/d;
            }
        }
        function Circle(x,y,d,b,s,c)
        {
            this.x = x;
            this.y = y;
            this.diameter = Math.round(d);
            this.radius = Math.round(d/2);
            this.bounciness = b;
            this.speed = s;
            this.color = c;
            this.deltaX = 0;
            this.deltaY = 0;
            this.drawnPosition = "";
            this.fill = function()
            {
                context.beginPath();
                context.arc(this.x+this.radius,this.y+this.radius,this.radius,0,Math.PI*2,false);
                context.closePath();
                context.fill();
            }
            this.clear = function()
            {
                context.fillStyle = "#ffffff";
                this.fill();
            }
            this.draw = function()
            {
                if (this.drawnPosition !== getCoordinates(this.x, this.y))
                {
                    context.fillStyle = this.color;
                    // if commented, the circle will be drawn if it is in the same position
                    //this.drawnPosition = getCoordinates(this.x, this.y);
                    this.fill();
                }
            }
            this.keepInBounds = function()
            {
                if (this.x < 0)
                {
                    this.x = 0;
                    this.deltaX *= -1 * this.bounciness;
                }
                else if (this.x + this.diameter > canvas.width)
                {
                    this.x = canvas.width - this.diameter;
                    this.deltaX *= -1 * this.bounciness;
                }
                if (this.y < 0)
                {
                    this.y = 0;
                    this.deltaY *= -1 * this.bounciness;
                }
                else if (this.y+this.diameter > canvas.height)
                {
                    this.y = canvas.height - this.diameter;
                    this.deltaY *= -1 * this.bounciness;
                }
            }
            this.followMouse = function()
            {
                // deltaX/deltaY will currently cause the circles to "orbit" around the cursor forever unless it hits a wall
                var centerX = Math.round(this.x + this.radius);
                var centerY = Math.round(this.y + this.radius);
                if (centerX < mouse.x)
                {
                    // circle is to the left of the mouse, so move the circle to the right
                    this.deltaX += this.speed;
                }
                else if (centerX > mouse.x)
                {
                    // circle is to the right of the mouse, so move the circle to the left
                    this.deltaX -= this.speed;
                }
                else
                {
                    //this.deltaX = 0;
                }
                if (centerY < mouse.y)
                {
                    // circle is above the mouse, so move the circle downwards
                    this.deltaY += this.speed;
                }
                else if (centerY > mouse.y)
                {
                    // circle is under the mouse, so move the circle upwards
                    this.deltaY -= this.speed;
                }
                else
                {
                    //this.deltaY = 0;
                }
                this.x += this.deltaX;
                this.y += this.deltaY;
                this.x = Math.round(this.x);
                this.y = Math.round(this.y);
            }
        }
        function getRandomDecimal(min, max)
        {
            return Math.random() * (max-min) + min;
        }
        function getRoundedNum(min, max)
        {
            return Math.round(getRandomDecimal(min, max));
        }
        function getRandomColor()
        {
            // array of three colors
            var colors = [];
            // go through loop and add three integers between 0 and 255 (min and max color values)
            for (var i = 0; i < 3; i++)
            {
                colors[i] = getRoundedNum(0, 255);
            }
            // return rgb value (RED, GREEN, BLUE)
            return "rgb(" + colors[0] + "," + colors[1] + ", " + colors[2] + ")";
        }
        function createCircle(i)
        {
            // diameter of circle
            var minDiameter = 25;
            var maxDiameter = 50;
            // bounciness of circle (changes speed if it hits a wall)
            var minBounciness = 0.2;
            var maxBounciness = 0.65;
            // speed of circle (how fast it moves)
            var minSpeed = 0.3;
            var maxSpeed = 0.45;
            // getRoundedNum returns a random integer and getRandomDecimal returns a random decimal
            var x = getRoundedNum(0, canvas.width);
            var y = getRoundedNum(0, canvas.height);
            var d = getRoundedNum(minDiameter, maxDiameter);
            var c = getRandomColor();
            var b = getRandomDecimal(minBounciness, maxBounciness);
            var s = getRandomDecimal(minSpeed, maxSpeed);
            // create the circle with x, y, diameter, bounciness, speed, and color
            circles[i] = new Circle(x,y,d,b,s,c);
        }
        function makeCircles()
        {
            var maxCircles = getRoundedNum(2, 5);
            for (var i = 0; i < maxCircles; i++)
            {
                createCircle(i);
            }
        }
        function drawCircles()
        {
            var ii = 0;
            for (var i = 0; ii < circles.length; i++)
            {
                if (circles[i])
                {
                    circles[i].draw();
                    ii++;
                }
            }
        }
        function clearCircles()
        {
            var ii = 0;
            for (var i = 0; ii < circles.length; i++)
            {
                if (circles[i])
                {
                    circles[i].clear();
                    ii++;
                }
            }
        }
        function updateCircles()
        {
            var ii = 0;
            for (var i = 0; ii < circles.length; i++)
            {
                if (circles[i])
                {
                    circles[i].keepInBounds();
                    circles[i].followMouse();
                    ii++;
                }
            }
        }
        function update()
        {
            requestMyAnimationFrame(update,10);
            updateCircles();
        }
        function draw()
        {
            requestMyAnimationFrame(draw,1000/60);
            context.clearRect(0,0,canvas.width,canvas.height);
            drawCircles();
        }
        function handleError(e)
        {
            //e.preventDefault();
            //console.error("    ERROR    ------    " + e.message + "    ------    ERROR    ");
        }
        window.addEventListener("load", function()
        {
            window.addEventListener("error", function(e)
            {
                handleError(e);
            });
            window.addEventListener("resize", function()
            {
                canvas.width = window.innerWidth - 20;
                canvas.height = window.innerHeight - 20;
            });
            window.addEventListener("mousemove", function(e)
            {
                mouse.x = e.layerX || e.offsetX;
                mouse.y = e.layerY || e.offsetY;
            });
            makeCircles();
            update();
            draw();
        });
    </script>
</body>
</html>

Upvotes: 1

Related Questions