附之前链接:
用canvas绘制漫天飞舞的雪花1
用canvas绘制漫天飞舞的雪花2

本次效果:22.gif

效果预览:https://codepen.io/andy-js/pen/YzPYQvz

废话不说,直接上代码
与之前的区别在于,增加了雪花随机出现和从上到下的效果。
并且这次利用了RAF来做动画。
下一篇会介绍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:用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;   //雪花外框大小
       this.x=x;
       this.y=y;
       this.angle=angle;
       
       this.ctx.save();
       this.init(); 
       this.bole();
       this.ctx.restore(); 
    };
    init(){  //初始化
        this.lineWidth=parseInt(this.width/60); //主干线的宽度
        this.lineHeight=this.width/2*0.8;  //主干线的 长度
        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);//重新映射画布上的 (0,0) 位置  映射到雪花位置

        //旋转  起始度
        if(this.angle!=0)this.ctx.rotate(  this.angle*Math.PI/180 );
    };
    bole(){
        for(let i=0;i<6;i++){
            this.ctx.lineCap="round";//向线条的每个末端添加圆形线帽。

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

            //画顶端圆
            this.ctx.beginPath();
            this.ctx.arc(0,-this.lineHeight,this.lineWidth*1.5,0,Math.PI*2,true);
            this.ctx.fill();

            
            //画支线
            this.branch();
            
            //旋转
            this.ctx.rotate(Math.PI/3);
        };
    };
    branch(){   //画分支
        let lineHeight=this.lineHeight;
        let start=0,    
            gap=parseInt(lineHeight /4);   //每根分支的间距
           
        for(let i=0;i<4;i++){
            this.ctx.lineCap="round";//向线条的每个末端添加圆形线帽。
            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){      //通过正余弦区取XY坐标 
        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);  //清除
    };
};


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);   //当前时间间隔
    renderSnow.background(w,h);

    //之前生产过的雪花
    let l=snows.length;
    for(let i=0;i<l;i++){
        let o=snows[i];
        o.y+=4;  //往下
        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;
        };
    };

    //新增的雪花,每次新增1个,随机位置,随机宽度
    
    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(rander);  //推荐使用  利用原生RAF绘制动画


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

andy
6 声望3 粉丝

贪财好色!经不住诱惑!