1

I have made a canvas with multiple hollow circles. And I am trying to animate it. I tried to use the method requestAnimationFrame, but it was unsuccessful. And if possible, I would prefer trying to stick with this method.

To avoid confusion in my code, I have added as much as reasonable comments which explains how the codes works. Note, that my knowledge regarding Javascript is far from good hence the amount of comments.

Also: Outside of the ending script tag, I am showing the lines of codes I tried to use for animation but was unsuccessful in doing so.

See the code below:

body {
    background-color: #000000;
}

canvas {
    padding: 0;
    margin: auto;
    display: block;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: #111416;
    border: 10px solid blue;
    border-style: double;
    box-shadow: 0 0 20px 5px blue;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <link rel="stylesheet" href="canvas.css">
    <canvas id="myCanvas" width="350" height="350"></canvas>

    <script>
    
    // Get id from the canvas element
    var canvas = document.getElementById("myCanvas");

    // Provide 2D rendering context for the drawing surface of canvas
    var context = canvas.getContext("2d");

    // Get width and height of the canvas element
    var canvW = document.getElementById("myCanvas").width;
    var canvH = document.getElementById("myCanvas").height;
    
    // Create a random range of numbers
    const randomRange = (min, max) => {
        return Math.random () * (max - min) + min;
    }

    // Class = Create multiple objects with the same properties 
    class Point {
        // Build the new object and pass parameters
        constructor(x, y){
            
            // Define properties
            // "this" refers to the scope of the class
            // class point contains propertie x and y
            this.x = x; 
            this.y = y;
        }
    }

    // Separate point from canvas
    // Make dot a new entity
    // Create another class

    class Agent {
        constructor(x, y){
            // First property is position using x and y parameters
            this.pos = new Point(x, y);
            
            // Create points with random radius
            this.radius = randomRange(4, 12);
        }

        // Create new method called draw
        // Pass paramter as reference to the context

        draw (context) {

            // Draw the points
            context.save();
            context.translate(this.pos.x, this.pos.y);
            context.beginPath();
            context.arc(0, 0, this.radius, 0, Math.PI * 2);
            context.lineWidth = 4;
            context.strokeStyle = "blue";
            context.stroke();
            context.restore();
        }

    }
   
    // Create empty array called
    // Note to myself: Cannot be written before the initialization of class agent
    const agents = [];

    // Create 40 random points using a for loop

    for (let i =0; i<40; i++){
        const x = randomRange(0, canvW);
        const y = randomRange(0, canvH);

        // push adds new items to the end of an array
        // push changes the length of an array
        // push returns the new length
        agents.push(new Agent (x, y));
        
        // Call function for each element in the array
        agents.forEach(agent => {
        agent.draw(context);
   
    });
    }

    </script>
    
<!--
        // Define velocity of point
        this.vel = new Point( randomRange(-1, 1), randomRange(-1, 1));
    
        // Add velocity to the points
        update() {
            this.pos.x += this.vel.x;
            this.pos.y += this.vel.y;
        }

        agent.update();

        const animate = () => {}
        requestAnimationFrame(animate);
        };
        animate();
-->

</body>
</html>

1 Answers1

1

I changed a few lines and commented them with 'Info:'.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <link rel="stylesheet" href="canvas.css">
    <canvas id="myCanvas" width="350" height="350"></canvas>

    <script>
    
    // Get id from the canvas element
    var canvas = document.getElementById("myCanvas");

    // Provide 2D rendering context for the drawing surface of canvas
    var context = canvas.getContext("2d");

    // Get width and height of the canvas element
    var canvW = document.getElementById("myCanvas").width;
    var canvH = document.getElementById("myCanvas").height;
    
    // Create a random range of numbers
    const randomRange = (min, max) => {
        return Math.random () * (max - min) + min;
    }
   
    // Create empty array called
    // Note to myself: Cannot be written before the initialization of class agent
    // Info: It can, maybe something else was wrong? Although, you might want to keep it together.
    const agents = [];

    // Class = Create multiple objects with the same properties 
    class Point {
        // Build the new object and pass parameters
        constructor(x, y){
            
            // Define properties
            // "this" refers to the scope of the class
            // class point contains propertie x and y
            this.x = x; 
            this.y = y;
        }
    }

    // Separate point from canvas
    // Make dot a new entity
    // Create another class

    class Agent {
        constructor(x, y){
            // First property is position using x and y parameters
            this.pos = new Point(x, y);

            // Define velocity of point.
            // Info: Moved velocity in class.
            // Todo: Decide where to handle velocity. Set it once? Update it later?
            this.vel = new Point(randomRange(-1, 1), randomRange(-1, 1));

            // Create points with random radius
            this.radius = randomRange(4, 12);
        }

        // Create new method called draw
        // Pass paramter as reference to the context

        draw (context) {
            // Draw the points
            // Info: Added fill to make individual elements visible
            context.save();
            context.translate(this.pos.x, this.pos.y);
            context.beginPath();
            context.arc(0, 0, this.radius, 0, Math.PI * 2);
            context.lineWidth = 4;
            context.strokeStyle = "blue";
            context.fillStyle = "white";
            context.fill();
            context.stroke();
            context.restore();
        }
        
        // Info: Moved update in class
        update() {
            this.pos.x += this.vel.x;
            this.pos.y += this.vel.y;
        }
    }

    // Create 40 random points using a for loop

    for (let i =0; i<40; i++){
        const x = randomRange(0, canvW);
        const y = randomRange(0, canvH);

        // push adds new items to the end of an array
        // push changes the length of an array
        // push returns the new length
        agents.push(new Agent (x, y));
    }

    // Info: Whole drawing and update process can be handled here
    const animate = () => {
        agents.forEach(agent => {
            agent.draw(context);
            agent.update();
        });
    
      requestAnimationFrame(animate);
    }

    animate();
    
    </script>

</body>
</html>
TheRemoteCoder
  • 172
  • 2
  • 12
  • Hello, thank you so much for helping me. Is there a way to only move the circles itself without showing the blue lines in the animation when the inevitably go outside of the boundaries of the canvas? It is actually quite close to the solution I wanted. – elbertainstein Oct 09 '22 at 19:05
  • Hi, glad I could help. I am not sure if I understand correctly. For the visuals, you can simply remove the stroke style. Do you mean the trace they leave (from the fill)? Then you could implement a reset in `animate()` before drawing all objects: https://stackoverflow.com/questions/2142535/how-to-clear-the-canvas-for-redrawing – TheRemoteCoder Oct 10 '22 at 19:30
  • Yes I meant the traces they leave behind. I apologize for my unclear question. I am not well versed with animate method since I didn't had the time reading the documentation and trying it out. I will read into the link you provided me. Thanks again. – elbertainstein Oct 11 '22 at 05:39