8. Draw flying snowflakes with canvas 3

Time:2020-3-20

Link before:
Using canvas to draw flying snowflake 1
Drawing flying snowflakes 2 with canvas

This effect:8. Draw flying snowflakes with canvas 3

Effect preview: https://codepen.io/andy-js/pen/yzpyqvz

No nonsense, just code it
The difference is that it increases the random appearance and top-down effect of snowflakes.
And this time I used RAF to do animation.
The next article introduces some features of Raf.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    < title > Andy JS: drawing flying snowflakes with canvas 3 < / Title >
    <style>
    *{margin:0;padding:0}
    html,body{height:100%;}
    body{
        background: url('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1578308683306&di=4da4218c7fa2ea098ebb0f4f2cb59d95&imgtype=0&src=http%3A%2F%2Fimg.pconline.com.cn%2Fimages%2Fupload%2Fupc%2Ftx%2Fwallpaper%2F1211%2F20%2Fc0%2F15914543_1353393939331.jpg') no-repeat center center;
        background-size: 100% 100%;
    }
    </style>
</head>
<body>

<script>
class Snowflake{
    constructor(ctx){
       this.ctx=ctx;
    };
    render({width,x,y,angle}){
       This. Width = width; // snowflake frame size
       this.x=x;
       this.y=y;
       this.angle=angle;
       
       this.ctx.save();
       this.init(); 
       this.bole();
       this.ctx.restore(); 
    };
    Init() {// initialization
        This. Linewidth = parseInt (this. Width / 60); // width of trunk line
        This. Lineheight = this. Width / 2 * 0.8; // length of trunk line
        if(this.lineHeight<1)this.lineHeight=1;
        this.heightArr=[ this.lineHeight*0.12,this.lineHeight*0.12,this.lineHeight*.2,this.lineHeight*0.3 ];

        this.ctx.lineWidth=this.lineWidth;
        this.ctx.strokeStyle='#fff';
        this.ctx.fillStyle="#fff";  

        This. CTX. Translate (this. X, this. Y); // remap the (0,0) position on the canvas to the snowflake position

        //Start of rotation
        if(this.angle!=0)this.ctx.rotate(  this.angle*Math.PI/180 );
    };
    bole(){
        for(let i=0;i<6;i++){
            This. CTX. Linecap = "round"; // adds a round cap to each end of the line.

            this.ctx.fillStyle="#fff";
            this.ctx.beginPath();
            this.ctx.moveTo(0,0);
            this.ctx.lineTo(0,-this.lineHeight);
            this.ctx.stroke();
            

            //Draw top circle
            this.ctx.beginPath();
            this.ctx.arc(0,-this.lineHeight,this.lineWidth*1.5,0,Math.PI*2,true);
            this.ctx.fill();

            
            // draw a branch line.
            this.branch();
            
            // rotation
            this.ctx.rotate(Math.PI/3);
        };
    };
    Branch() {// Branch
        let lineHeight=this.lineHeight;
        let start=0,    
            Gap = parseInt (lineheight / 4); // spacing of each branch
           
        for(let i=0;i<4;i++){
            This. CTX. Linecap = "round"; // adds a round cap to each end of the line.
            let spot=this.getXY(45,this.heightArr[i]); 
            this.ctx.beginPath();
            this.ctx.moveTo(0,start);
            this.ctx.lineTo(spot.x, start+spot.y );
            this.ctx.stroke();
        
            this.ctx.beginPath();
            this.ctx.moveTo(0,start);
            this.ctx.lineTo(-(spot.x), start+spot.y );
            this.ctx.stroke();

            start-=gap;
        };
    };
    Getxy (angle, radius) {// get the XY coordinate through the sine cosine area 
        return {
            x:Math.sin((180-angle)*Math.PI/180)*radius,
            y:Math.cos((180-angle)*Math.PI/180)*radius
        }
    };
    background(w,h){
        // this.ctx.fillStyle="#000";
        // this.ctx.fillRect(0,0,w,h); 
        This.ctx.clearrect (0,0, W, H); // clear
    };
};


var oC1=document.createElement('canvas');
    ctx = oC1.getContext("2d");
var w=document.documentElement.clientWidth,h=document.documentElement.clientHeight
oC1.setAttribute('width',w);
oC1.setAttribute('height',h);
document.body.appendChild(oC1);


var renderSnow=new Snowflake(ctx);
var snows=[];

function rander(a){
    //Console.log (a); // current time interval
    renderSnow.background(w,h);

    //Snowflakes produced before
    let l=snows.length;
    for(let i=0;i<l;i++){
        let o=snows[i];
        o. Y + = 4; // down
        o.angle+=15;
        if(o.angle>360)o.angle=o.angle%360;
        renderSnow.render(o);
        if(o.y>h+o.width/2){
            snows.splice(i,1);
            i--;
            l=snows.length;
        };
    };

    //Newly added snowflakes, 1 at a time, random position, random width
    
    let snowWidth=rnd(20,50);
    let newO={
        ctx:ctx,
        width:snowWidth,
        x:rnd(0,w),
        y:-snowWidth,
        angle:rnd(0,360)
    };
    snows.push(newO);
    renderSnow.render(newO);
  
    
     requestAnimationFrame(rander);
};

Requestanimationframe (range); // it is recommended to use native RAF for animation


function rnd(n,m){
    return Math.random()*(m-n+1)+n;
};
</script>
</body>
</html>

Recommended Today

How to connect Oracle database with PL / SQL developer

Before because of the project, Oracle database was needed. Because of the limited time, it was impossible to learn from the foundation, and the command interface of Oracle operation was too unfriendly, so we found PL / SQL developer, a very useful software, to indirectly use the database. Here is a brief introduction of how […]