利用canvas模拟绘制下雪

发布时间:2017-02-16 浏览次数:3144 文章来源:个人博客

有时候为了使得网站变得更加酷炫,需要做些效果,比如下雪,下面就说说用canvas实现下雪的吧。


首先,实现动画,必不可少的就是requestAnimationFrame这个方法了,具体的可以百度查询

定义requestAnimationFrame

requestAnimationFrame = window.requestAnimationFrame||
                        window.mozRequestAnimationFrame ||
                        window.webkitRequestAnimationFrame||
                        window.msRequestAnimationFrame||
                        window.oRequestAnimationFrame||
                        function(callback){setTimeout(callback,1000/60);};


接着,定义雪的属性函数

//x,y是雪的中心坐标,radius是雪的半径
//fn是雪位置变化的函数
function Snow(x,y,radius,fn){
  this.x=x;
  this.y=y;
  this.r=radius;
  this.fn=fn;
 }  
 
 //更新雪的坐标
 Snow.prototype.update=function(){
  this.x = this.fn.x(this.x,this.y);
  this.y = this.fn.y(this.y,this.y);
  if(this.x > window.innerWidth || this.x < 0 || this.y > window.innerHeight || this.y < 0 )
  {
   this.x = getRandom('x');
   this.y=0;
  }
 }
 
 //在canvas上画出雪花
 Snow.prototype.draw = function(ctx){
  var grd = ctx.createRadialGradient(this.x,this.y,0,this.x,this.y,this.r);
  grd.addColorStop(0,"rgba(255,255,255,0.8)");
  grd.addColorStop(0.5,"rgba(255,255,255,0.4)");
  grd.addColorStop(1,"rgba(255,255,255,0)");
  ctx.fillStyle=grd;
  ctx.fillRect(this.x-this.r,this.y-this.r,this.r*2,this.r*2);  
 }


现在,建立一个雪的数组保存每个雪的对象。以便requestAnimationFrame在调用时候,不停的更改各个雪花的位置,从而实现下雪的效果

SnowList = function(){
  this.list=[];
 }
 SnowList.prototype.push=function(snow){
  this.list.push(snow);
 }
 SnowList.prototype.update=function(){
  for(var i = 0,len = this.list.length;i<len;i++){
   this.list[i].update();
  }
 }
 SnowList.prototype.draw=function(ctx){
  for(var i=0,len = this.list.length;i<len;i++){
   this.list[i].draw(ctx);
  }
 }
 SnowList.prototype.get=function(i){
  return this.list[i];
 }
 SnowList.prototype.size=function(){
  return this.list.length;
 }

雪是随机掉落的,因此需要做个随机的函数获取雪的位置

function getRandom(option){
  var ret,random;
  switch(option){
   case 'x':
     ret=Math.random()*window.innerWidth;
     break;
   case 'y':
     ret=Math.random()*window.innerHeight;
     break;
   case 'r':
     ret=10+(Math.random()*6);
     break;
   case 'fnx':
     random = 27+Math.random()*100;
     ret = function(x,y){
      return x + 0.5 * Math.sin(y/random);
     }     
     break;
   case 'fny':
     random=0.4+Math.random()*1.4;
     ret = function(x,y){
      return y +random;
     };
     break;
  }
  return ret;  
 }

接着,主函数,用于构造雪并且掉落

function startSnow(){
  var canvas = document.createElement('canvas'),ctx;
  canvas.width=window.innerWidth;
  canvas.height=window.innerHeight;
  canvas.setAttribute('style','position: fixed;left: 0;top: 0;pointer-events: none;');
  canvas.setAttribute('id','canvas_snow');
  document.getElementsByTagName ('body')[0].appendChild (canvas); 
  ctx =canvas.getContext('2d');
  //至此,canvas画布已经建立好
  
  //初始化雪的数组
  var snowList = new SnowList();
  //小于100表示有100个雪花
  for(var i = 0 ; i<100;i++){
   var snow,randomX,randomY,randomR,randomFnx,randomFny;
   randomX = getRandom('x');
   randomY = getRandom('y');
   randomR = getRandom('r');
   randomFnx = getRandom('fnx');//函数
   randomFny = getRandom('fny');//返回函数
   //初始化第I个雪花
   snow = new Snow(randomX,randomY,randomR,{x:randomFnx,y:randomFny});
   //将第I个雪花画到canvas上面
   snow.draw(ctx);
   //加入数组
   snowList.push(snow);
  }
  //动画
  requestAnimationFrame(function down(){
    //清除原来上面的雪花
    ctx.clearRect(0,0,canvas.width,canvas.height);
    //计算每一片雪花的新坐标
    snowList.update();
    //画上每片雪花
    snowList.draw(ctx);
    //定时又从新执行当前函数
    requestAnimationFrame(down);
  })
 }
 
 //做个窗口监听,以便保证canvas是满屏的
 window.onresize = function () {  
        var canvasSnow = document.getElementById('canvas_snow');  
        canvasSnow.width = window.innerWidth;  
        canvasSnow.height = window.innerHeight;  
    }

最后,运行起来,即可看的下雪的效果。。


注意:雪花是白色的。。背景不能是白色。。

key-word
canvas学习 canvas下雪 canvas动画 canvas绘制雪 H5