JS encapsulated canvas bubble animation

Posted by VanPEP on Tue, 15 Oct 2019 19:35:01 +0200

Reason

Recently in the implementation of some more dynamic visual page, need a bubble generated animation, wrote this code.

logic

First, we need to pass in a canvas dom to get its width and height, initialize and declare a specific length of bubble array (the length can be passed in from the outside), each bubble has radius, speed, initialization location and other attributes.
Then you need to execute the rendering method, call clearRect() before each rendering, empty the canvas, and then call the rendering method by window.requestAnimationFrame() cycle.
When initializing a drawing bubble, the position can be random or generated at the bottom. Each time the height position of the bubble changes, it reappears from the bottom when it reaches the top of the canvas.

Code

class BubbleAnimate {
    constructor(canvas, number=20,radius=6,color=[255,255,255],speed=0.2,speedRandomPercent=0.5,startFull=true) {
        try{
            this.canvas = canvas;
        }catch{
            throw("please provide canvas dom"); 
            return ;
        }
        this.ctx = canvas.getContext('2d');
        this.width=canvas.width;
        this.height=canvas.height;
        this.radius=radius;
        this.color=color;
        this.speed=speed;
        this.bubbles = [];
        this.speedRandomPercent=speedRandomPercent;
        this.startFull=startFull;
        for(let i=0; i<number;i++) {
            this.bubbles.push({
                isReborn:true,
                speed: speed+(Math.random()*2-1)*speedRandomPercent*speed,
            });
        }
        this.renderCanvas();
    };
    renderCanvas() {
        this.ctx.clearRect(0,0,this.width,this.height);
        this.renderBubbles();
        window.requestAnimationFrame(() => this.renderCanvas());
    };
    renderBubbles() {
        //Bubble
        let initPoint = [this.width/2,this.height];
        for(let i = 0;i<this.bubbles.length;i++) {
            let bubble = this.bubbles[i];
            if(bubble.isReborn) {
                let x = (Math.random()-0.5)*this.width*0.96 + initPoint[0];
                //Bubble radius generated randomly in a certain range
                let bubbleRadius = this.radius+ Math.floor(Math.random()*2-1)*0.5;
                //Judge whether the bubble is full during initialization
                let y = this.startFull?this.height*Math.random():(initPoint[1] - bubbleRadius);
                bubble.radius = bubbleRadius;
                bubble.currentLocation = [x, y];
                let opacity = 0.2 + 0.4* Math.random();
                bubble.color = `rgba(${this.color[0]}, ${this.color[1]},${this.color[2]}, ${opacity})`;
                bubble.isReborn = false;
            }else {
                this.renderBubble(bubble);
                if(bubble.currentLocation[1]<= bubble.radius){
                    bubble.isReborn = true;
                }![Picture description][1]
                bubble.currentLocation[1] = bubble.currentLocation[1] -bubble.speed;
            }
        }
    }
    renderBubble(item) {
        this.ctx.beginPath();
        this.ctx.arc(...item.currentLocation, item.radius, 0, 2*Math.PI);
        this.ctx.fillStyle = item.color;
        this.ctx.fill();
    }
}

Demo address

Demo address

Code address

Code address

Effect

Topics: Front-end