Home > Enterprise >  How to animate multiple objects inside canvas?
How to animate multiple objects inside canvas?

Time:10-11

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>

CodePudding user response:

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>
  • Related