用jsfiddle 製作聖誕節的動畫

in cn •  29 days ago

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();

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  trending

这个有意思,来晚了呀

真开心再次见到你!cn区点赞机器人 @cnbuddy 谢谢你对cn区的贡献。 @cnbuddy 旨在助力cn区快速发展,更多cn区动态,请查看我的主页。欢迎关注我们的大股东 @skenan,并注册使用由其开发的 CNsteem.com。如果我打扰到你,请回复“取消”。

Congratulations! This post has been upvoted from the communal account, @minnowsupport, by tensaix2j from the Minnow Support Project. It's a witness project run by aggroed, ausbitbank, teamsteem, theprophet0, someguy123, neoxian, followbtcnews/crimsonclad, and netuoso. The goal is to help Steemit grow by supporting Minnows and creating a social network. Please find us in the Peace, Abundance, and Liberty Network (PALnet) Discord Channel. It's a completely public and open space to all members of the Steemit community who voluntarily choose to be there.

If you would like to delegate to the Minnow Support Project you can do so by clicking on the following links: 50SP, 100SP, 250SP, 500SP, 1000SP, 5000SP. Be sure to leave at least 50SP undelegated on your account.

This post has received a 1.56 % upvote from @drotto thanks to: @banjo.