Canvas绘制雨滴(二)之setInterval与setTimeout

多谢腾讯视频课的万章老师指点。

鉴于setInterval的恶劣性质,进行修改,用setTimeout实现setInterval,并放在Rain原型的move属性中。运行结果:画面显示混乱,浏览器卡死。。

原因是:
setTimeout与setInterval尽量不要写在函数里, 无论是定时器还是延时器,他们会严重阻碍程序的正常运行流程。

这次程序又多次调用定时器函数,重复执行,性能降低。

此外,设置定时器属于业务代码,而在原型中定义的属性属于逻辑代码。应该将两者分开写。便于debug和整理。

至于,如何区分业务代码与逻辑代码,还要进一步的学习( ▼-▼ )飙泪

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <title>雨滴下落2</title>
  <style>
  body{margin:0;}
  #rain{display:block;
  background-color:black;}
  </style>
 </head>
 <body>
 <!--卡死了的代码->
  <canvas id="rain"></canvas>
  <script>
  /*
    1.获取
        1.1 设置canvas宽高
        1.2 获取窗口宽高
        1.3 当窗口大小变化时,改变canvas宽高
    2.绘制雨滴
    3.多个雨滴
    3.雨滴降落
        */
    //1.设置canvas大小
    var can=document.getElementById("rain");//为can元素设置宽高,而不是画布getcontext
    //var can=document.getContext(canva);
    var w=window.innerWidth;//使用全局变量保存宽高,减少访问,便于调用
    var h=window.innerHeight;//属性名字为inner-width/height
    can.width=w;
    can.height=h;
    window.onresize=function(){
        w=window.innerWidth;
        h=window.innerHeight;//需要重新为w,h赋值
        can.width=w;
        can.height=h;
        }
    //2.绘制雨滴
    //绘制一滴
    /*
    function random(min,max){
        return Math.random()*(max-min)+min;
    }
    var x=random(0,w);
    var y=0;//起点
    var canContent=can.getContext("2d");//画布
    //初始位置绘制
    canContent.fillStyle="rgb(0,255,255)";
    canContent.fillRect(x,y,5,20);//雨滴
    //移动--动画
    function draw(){
        canContent.fillStyle="rgba(0,0,0,0.01)";
        canContent.fillRect(0,0,w,h);//毛玻璃
        canContent.fillStyle="rgb(0,255,255)";
        canContent.fillRect(x,y++,5,20);//雨滴位置变化
    }
    setInterval(draw,1000/60);

    */


    function random(min,max){
        return Math.random()*(max-min)+min;
    }

    function Rain(){};
    var canContent=can.getContext("2d");
    Rain.prototype={
        init:function(){
            //参数
            this.x=random(0,w);
            this.y=0;//起点
            this.l=random(0.8*h,0.9*h);//下落高度
            this.v=random(4,5);//下落速度
            this.r=1;//水花的初始半径
            this.vr=random(1,2);//半径扩大的速度
            this.rmax=random(50,60);//开始变透明的半径
            this.a=1;//初始透明度
            this.va=0.98;//透明度的变化
            this.amin=0.2;
        },
        draw:function(){
            //绘制
            //.1绘制下落
            if(this.y<this.l){
                canContent.fillStyle="rgb(0,255,255)";
                canContent.fillRect(this.x,this.y,2,20);//雨滴位置变化
            }else{
            //.2绘制水花
                canContent.strokeStyle="rgba(0,255,255,"+this.a+")";//
                //"rgba(0,255,255,this.a)";//会出错,读取字符串,无法获得变量变化值
                canContent.beginPath();
                canContent.arc(this.x,this.y,this.r,0,2*Math.PI,false);
                canContent.stroke();
            }

        },
        update:function(){
            //更新坐标值,并绘制
            //.1下落过程的坐标更新
            if(this.y<this.l){
                this.y+=this.v;
            }else{
            //.2水花过程的坐标更新(坐标不变,半径变化,透明度变化)
            //更新后绘制雨滴:

                /*
                透明度的变化取决于半径大小
                this.r+=this.vr;
                if(this.r<this.rmax){
                    this.a*=this.va;
                }else{
                    this.init();
                }
                }
                */
                //透明度的变化取决于半径大小,半径大小取决于透明度大小
                if(this.a>this.amin){
                        this.r+=this.vr;
                        if(this.r>this.rmax){
                            this.a*=this.va;//乘更自然
                        }
                    }
                    else{
                        this.init();//透明度变了的话,回到天上
                    }
                }
                this.draw();
                console.log("update:")
                console.log(this);

        },
        move:function(){
        //移动显示:覆盖不透明度不同的层数,并不断在新的位置绘制雨滴,所形成的
            canContent.fillStyle="rgba(0,0,0,0.05)";
            canContent.fillRect(0,0,w,h);//毛玻璃
            console.log("move:")
            console.log(this);
            this.update();

            //setTimeout(arguments.callee,1000/60);
            // requestAnimationFrame(this.move);//未执行
            // console.log("222");
            moveRain.call(this);//用延时器实现定时器
            /*//移在外部,减少内存占用
            function moveRain(){
                 this.move();
                  setTimeout(moveRain,1000/60);
            }
            */
        }
    }
//用延时器实现定时器
function moveRain(){
         this.move();
         setTimeout(moveRain,1000/60);
            }

//创建30个
for(var i=0;i<30;i++){
    setTimeout(createRain,300*i);//隔300*i ms执行一次createRain
}//同时创建30个setTimeout,但每个setTimeout开始执行的时间不同

function createRain(){
    var rain=new Rain();
    rain.init();
    rain.draw();
    rain.update();
    rain.move();
    //setInterval(rain.move,1000/60);//此时还没有rain
    //在第0秒就开始执行
}
  </script>
 </body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

picoasis

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值