用jsfiddle 製作聖誕節的動畫

tensaix2j(58)
Published in
#cn
Words
193
Reading
1 min
9y
Listen to this post
~1 min

christmas.png

這是去年聖誕節時閒著沒事, 在jsfiddle 弄的聖誕節動畫。 jsfiddle 是一個給人家寫javascript 可以馬上測試效果的地方。 每個作品都有一個連接。

完成動畫在此:

https://jsfiddle.net/87zt93sz/3/

以下大概講解如何做下雪的部分

  1. 首先,在html 放一個 canvas 如下:

    <canvas id="cv" width="600px" height="400px"></canvas>

  1. 用 requestAnimationFrame 設一個循環呼喚的 timer

    this.update = function() {
        var cmt = this;
        window.requestAnimationFrame( function() {
            cmt.update();
        });
    }

  1. 下雪的animation, 每顆雪都有坐標xy, 動畫的每一tick, y 就直直下, x 則用到余弦(cos) 來控制x 左右漂浮的移動。 雪的大小也可以隨機設定 。

    for ( i = 0 ; i < this.snows.length ; i++) {
        
      this.snows[i].y += 1;
      this.snows[i].x += this.snows[i].cr * Math.cos(this.snows[i].tick);
      this.snows[i].tick += 0.01;
      if ( this.snows[i].y > this.canvas.height ) {
        this.snows[i].y = Math.random() * 50 - 50;
        this.snows[i].x = Math.random() * this.canvas.width;
        this.snows[i].cr = Math.random() * 2 - 1;
            this.snows[i].tick = Math.random();
      }
    }
    this.tick += 1;
    this.draw();

    
  1. 在draw() 裡把每顆雪畫到canvas 上,只需要用到 * 這個符號, 用 ctx.fillText

    for ( i = 0 ; i < this.snows.length ; i++ ) {
        this.ctx.fillStyle =  "rgba( 0 , 0 ,0, " + (i/this.snows.length) +")";
        this.ctx.font = i +"px Comic Sans";
        this.ctx.fillText( "*",this.snows[i].x , this.snows[i].y);
    }
    

祝大家聖誕節愉快!

完整代碼:

    
    function Christmas() {
        
      this.snows = [];
      this.tick = 0;
      
      this.init = function() {
        
        this.canvas = document.getElementById("cv");
            this.canvas.style.backgroundColor = "#ffffff";
            this.ctx = this.canvas.getContext('2d');
      
        for ( i = 0 ; i < 50 ; i++ ) {
            obj = {}
          obj.x = Math.random() * this.canvas.width;
          obj.y = Math.random() * this.canvas.height;
          obj.tick = Math.random();
          obj.cr = Math.random() * 4 - 2;
            this.snows.push(obj);
        }
       
        
        this.update();
            
      }
    
      this.update = function() {
        
        for ( i = 0 ; i < this.snows.length ; i++) {
            
          this.snows[i].y += 1;
          this.snows[i].x += this.snows[i].cr * Math.cos(this.snows[i].tick);
          this.snows[i].tick += 0.01;
          if ( this.snows[i].y > this.canvas.height ) {
            this.snows[i].y = Math.random() * 50 - 50;
            this.snows[i].x = Math.random() * this.canvas.width;
            this.snows[i].cr = Math.random() * 2 - 1;
                this.snows[i].tick = Math.random();
          }
        }
        this.tick += 1;
        this.draw();
        
        var cmt = this;
        window.requestAnimationFrame( function() {
                cmt.update();
            });
      }
    
        this.draw = function() {
        
        this.ctx.clearRect( 0,0, this.canvas.width , this.canvas.height );
        
        this.drawChrismasTree(500, 160,  20 );
        this.drawChrismasTree(420, 180,  12 );
        
      
        for ( i = 0 ; i < this.snows.length ; i++ ) {
            this.ctx.fillStyle =  "rgba( 0 , 0 ,0, " + (i/this.snows.length) +")";
          this.ctx.font = i +"px Comic Sans";
                this.ctx.fillText( "*",this.snows[i].x , this.snows[i].y);
            }
        
        var mrcm_fontsize = ( Math.cos(this.tick / 100 ) + 15 ) * 3   ;
        this.ctx.font = mrcm_fontsize + "px Mountains of Christmas";
            this.ctx.fillText( "Merry Christmas!", 170, 120);
            
      }
      
      
      this.drawChrismasTree = function( x , y , size) {
        
        var posoffset   =    Math.cos(this.tick/50) * 5;
        var curveoffset = Math.cos(this.tick/50) * 0.1;
        
        for ( i = 4 ; i >= 0 ; i-- ) {
            this.drawCone( x + (5 - i) * posoffset ,y + i*15 ,size+ i* 15 , (5-i)* curveoffset );
        }
        this.drawStar( x + 5 * posoffset ,y - size/4, size/2, size/4  , 2 * curveoffset);      
      }
      
      
      
      
      
      this.drawStar = function(cx,cy,outerRadius,innerRadius , rotated_shift){
          
          var rot = Math.PI / 2 * 3 + rotated_shift;
          var x=cx;
          var y=cy;
          var step=Math.PI/5;
          
          this.ctx.beginPath();
          
          x = cx+Math.cos(rot) * outerRadius;
          y = cy+Math.sin(rot) * outerRadius;
          this.ctx.moveTo( x, y );
          
          for(i = 0 ; i < 5 ;i++ ){
          
            x = cx+Math.cos(rot) * outerRadius;
            y = cy+Math.sin(rot) * outerRadius;
            this.ctx.lineTo(x,y)
            
                    rot += step
    
            x = cx+Math.cos(rot) * innerRadius;
            y = cy+Math.sin(rot) * innerRadius;
            this.ctx.lineTo(x,y)
            rot+=step
          }
          
          
          x = cx+Math.cos(rot) * outerRadius;
          y = cy+Math.sin(rot) * outerRadius;
          this.ctx.lineTo( x, y );
          
          this.ctx.closePath();
          this.ctx.stroke();
          this.ctx.fill();
        }
      
      this.drawCone = function( x, y, size , rotated_shift ) {
        
        this.ctx.beginPath();
        var cy = y + size/2;
            
        var theta_1 = Math.PI   / 4 + rotated_shift;
        var theta_2 = Math.PI *3/ 4 + rotated_shift;
        
        this.ctx.moveTo( x, y  );
        
        this.ctx.lineTo( x  + size * Math.cos(theta_2),  
                                     cy + size * Math.sin(theta_2));
        
        this.ctx.moveTo( x, y  );
        this.ctx.lineTo( x   + size * Math.cos(theta_1),  
                                        cy + size * Math.sin(theta_1));
        
         
         
         
            this.ctx.arc( x , cy , size , theta_1 , theta_2);
            
        
        this.ctx.fillStyle = 'white';
        this.ctx.fill();
        this.ctx.strokeStyle = 'black';
        this.ctx.stroke();
        
        this.ctx.closePath();
      
      }
    }
    
    var obj = new Christmas();
    obj.init();

用jsfiddle 製作聖誕節的動畫 | Ecency