Step by step create canvas ball animation

Time:2021-3-2

The methods we need to use canvas are as follows:

context.arc(x, y, r, sAngle, eAngle, counterclockwise);

Step 1: draw a small ball

var  canvas = document.getElementById('canvas'),
     ctx = canvas.getContext('2d'),
     w =  canvas.width , // width of canvas
     h =  canvas.height , // height of canvas
     Posx = 20, // define the center X coordinate
     Posy = 20, // define the Y coordinate of the center of the circle 
     Radius = 20; // define radius
ctx.clearRect (0, 0, W, H); // clear canvas
ctx.beginPath (); // start drawing
ctx.arc (posX,posY,radius,0,2* Math.PI ); // draw a circle
ctx.fillStyle  ='Red '; // fill color of circle
ctx.closePath (); // closed path
ctx.fill (); // fill

Online preview:https://codepen.io/jianxiujiu…

Step 2: let the ball move

The principle of making the ball move is to constantly change the coordinate position of the ball and redraw it.
Redrawing can use setinterval, setTimeout, or request standardization frame. The differences between them are not explained in detail here. For details, please refer to an article of my good friends:SetTimeout and requestanimation frame

window.requestAnimFrame = (function(){
    return window.requestAnimationFrame       || 
        window.webkitRequestAnimationFrame || 
        window.mozRequestAnimationFrame    || 
        window.oRequestAnimationFrame      || 
        window.msRequestAnimationFrame     ||
        function(callback){
            window.setTimeout(callback, 1000 / 60);
        };
})();
var canvas = document.getElementById('canvas'),
    ctx = canvas.getContext('2d'),
    w = canvas.width,
    h = canvas.height,
    Posx = 20, // X-axis position of the ball
    Posy = 20, // Y-axis position of the ball
    Speedx = 3, // ball X-axis speed
    Speedy = 3, // ball Y-axis speed
    Radius = 20; // radius of the ball

    function ani(){
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        posX += speedX;
        posY += speedY;     
        ctx.beginPath();
        ctx.arc(posX,posY,radius,0,2*Math.PI);
        ctx.fillStyle = 'red';
        ctx.closePath();
        ctx.fill();   
        if(posY < h - radius){ 
            Requestanimframe (ANI) // if the y-axis position does not exceed the height of the container, it will move all the time
        }
    }
    ani();

Online preview:https://codepen.io/jianxiujiu…

Step 3: collision animation of a small ball

Next, let’s let the ball move and collide around the canvas.

window.requestAnimFrame = (function(){
    return window.requestAnimationFrame       || 
        window.webkitRequestAnimationFrame || 
        window.mozRequestAnimationFrame    || 
        window.oRequestAnimationFrame      || 
        window.msRequestAnimationFrame     ||
        function(callback){
            window.setTimeout(callback, 1000 / 60);
        };
})();
var canvas = document.getElementById('canvas'),
    ctx = canvas.getContext('2d'),
    w = canvas.width,
    h = canvas.height,
    posX = 20,
    posY = 20,
    Speedx = 2, // ball X-axis speed
    Speedy = 2, // ball Y-axis speed
    Startspeedx = 2, // initial velocity of ball X-axis
    Startspeed = 2, // initial velocity of ball y-axis
    Radius = 20; // radius of the ball

    function ani(){       
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        posX += speedX;
        posY += speedY;
        
        //The ball rebounded when it hit the wall
        if(posY > h - radius){ 
            speedY*=-1;
        }
        if(posX > w - radius){
            speedX*=-1;  
        }
        if(posY < radius){
            speedY = startSpeedY;
            posY = radius;
        }
        if(posX < radius){
            speedX = startSpeedX;
            posX = radius;
        }
        
        ctx.beginPath();
        ctx.arc(posX,posY,radius,0,2*Math.PI);
        ctx.fillStyle = 'red';
        ctx.closePath();
        ctx.fill();
        requestAnimFrame(ani);
    }

    ani();

Online preview:https://codepen.io/jianxiujiu…

Step 4: collision animation of multiple balls

window.requestAnimFrame = (function(){
    return window.requestAnimationFrame       || 
        window.webkitRequestAnimationFrame || 
        window.mozRequestAnimationFrame    || 
        window.oRequestAnimationFrame      || 
        window.msRequestAnimationFrame     ||
        function(callback){
            window.setTimeout(callback, 1000 / 60);
        };
})();
var canvas = document.getElementById('canvas'),
    ctx = canvas.getContext('2d'),
    w = canvas.width,
    h = canvas.height,
    posX,
    posY,
    speedX,
    speedY,
    radius;

    Function randomnum (m, n) {// random function
        return Math.floor(Math.random() * (n - m + 1) + m);
    }

    Var balls = [] // create a ball array
    function getBall(){
        For (n = 0; n < 20; N + +) {// the number of balls
            Radius = randomnum (10,20), // radius random 10-20px
            Posx = randomnum (radius, w-radius), // X-axis position is random
            Posy = randomnum (radius, h-radius), // Y-axis position is random
            Speedx = randomnum (3,6), // X-axis velocity is random
            Speedy = randomnum (1,2), // Y-axis velocity is random
            Startspeedx = startspeedx, // record the starting speed of x-axis
            Startspeed = startspeed; // record the starting speed of x-axis
            Fillcolor ='rgb ('+ randomnum (0255) +', '+ randomnum (0255) +', '+ randomnum (0255) +'); // the color of the ball is random
            var ball = {
                radius : radius,
                posX : posX,
                posY : posY,
                speedX : speedX,
                speedY : speedY,
                startSpeedX : startSpeedX, 
                startSpeedY : startSpeedX,
                fillColor : fillColor
            }
            balls.push (ball) // save the generated ball to the array
        }    
    }
    getBall();   
            
    function draw(){     
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        var l = balls.length; 
        For (VaR I = 0; I < L; I + +) {// draw ball animation one by one
            ctx.beginPath();  
            ballCur = balls[i];
            ballCur.posX += ballCur.speedX;
            ballCur.posY += ballCur.speedY;
            if(ballCur.posY > h - ballCur.radius){
                ballCur.speedY*=-1;
            }
            if(ballCur.posX > w - ballCur.radius){
                ballCur.speedX*=-1;  
            }
            if(ballCur.posY < ballCur.radius){
                ballCur.speedY = startSpeedY;
                ballCur.posY = ballCur.radius;
            }
            if(ballCur.posX < ballCur.radius){
                ballCur.speedX = startSpeedX;
                ballCur.posX = ballCur.radius;
            }            
                               
            ctx.arc(ballCur.posX,ballCur.posY,ballCur.radius,0,2*Math.PI);        
            ctx.fillStyle = ballCur.fillColor;
            ctx.closePath();
            ctx.fill();
           
        }  
        requestAnimFrame(draw);    
    }        
    draw();

Online preview:https://codepen.io/jianxiujiu…

Step 5: small ball for custom picture animation

After the ball moves, if you want the ball to be a picture, you need to use another method of canvas

context.drawImage (image, x, y); // position the image on the canvas:
context.drawImage (image, x, y, width, height); // position the image on the canvas and specify the width and height of the image
context.drawImage (image, sourcex, sourcey, sourcewidth, sourceheight, destx, desty, destwidth, destheight); // cut the image and locate the cut part on the canvas

Unlike drawing ordinary ball, when drawing picture ball, we need to load the code of previous animation before executing. And the collision position also needs to be adjusted.

window.requestAnimFrame = (function(){
    return window.requestAnimationFrame       || 
        window.webkitRequestAnimationFrame || 
        window.mozRequestAnimationFrame    || 
        window.oRequestAnimationFrame      || 
        window.msRequestAnimationFrame     ||
        function(callback){
            window.setTimeout(callback, 1000 / 60);
        };
})();
var canvas = document.getElementById('canvas'),
    ctx = canvas.getContext('2d'),
    w = canvas.width,
    h = canvas.height,
    Ballwidth = 60, // picture ball width
    posX,
    posY,
    speedX,
    speedY;
    var img = new Image();
    img.src = 'img/ball.png';
    img.onload = function(){     
        getBall();  
        draw();
    }

    function randomNum(m,n) {
        return Math.floor(Math.random() * (n - m + 1) + m);
    }

    var balls = []
    function getBall(){
        for( n = 0; n < 20;n++){   
            posX = randomNum(ballWidth,w - ballWidth),
            posY = randomNum(ballWidth,h - ballWidth),
            speedX = randomNum(3,7),
            speedY = randomNum(4,8),
            startSpeedX = speedX,
            startSpeedY = speedY;
            Ballpicpos = randomnum (0,4) * 60; // the position of the ball image is random
            var ball = {
                posX : posX,
                posY : posY,
                speedX : speedX,
                speedY : speedY,
                startSpeedX : startSpeedX, 
                startSpeedY : startSpeedX,
                ballPicPos : ballPicPos
            }
            balls.push(ball);                  
        }   
    }
     
            
    function draw(){     
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        var l = balls.length;
        for(var i = 0;i<l;i++){  
            ballCur = balls[i];
            ballCur.posX += ballCur.speedX;
            ballCur.posY += ballCur.speedY;
            if(ballCur.posY > h - ballWidth){
                ballCur.speedY*=-1;
            }
            if(ballCur.posX > w - ballWidth){
                ballCur.speedX*=-1;  
            }
            if(ballCur.posY < 0){
                ballCur.speedY = startSpeedY;
                ballCur.posY = 0;
            }
            if(ballCur.posX < 0){
                ballCur.speedX = startSpeedX;
                ballCur.posX = 0;
            }                            
           
           ctx.beginPath(); 
           ctx.fillStyle = ctx.drawImage(img,0,ballCur.ballPicPos,ballWidth,ballWidth,ballCur.posX,ballCur.posY,ballWidth,ballWidth);
           ctx.fill();
           ctx.closePath();
           ctx.restore();
           
        }  
        requestAnimFrame(draw);  
    }

Online preview:https://codepen.io/jianxiujiu…

PS: if the value of the picture position of the ball is greater than the position of the picture itself, there will be a bug in the picture displayed under ie11.