《每週一點canvas動畫》——波形運動

在上一節咱們介紹了canvas動畫中有關三角函數的內容,以及一個跟隨鼠標旋轉的箭頭動畫。這一節主要介紹三角函數的波形運動。包括:html

  1. 平滑運動canvas

  2. 線性運動bash

  3. 脈衝運動dom

1.Sin函數的波形

sin函數的波形想必騷年們不會感到陌生,其圖形以下所示:函數

圖片描述

若是想要取得sin函數在[0, 2π]之間的值,非連續的狀況下,能夠這樣估算。動畫

for(var angle=0; angle<Math.PI*2; angle+=0.1){
        console.log(Math.sin(angle)); //打印出角度對應的sin值
    }

1.平滑運動

首先介紹Math.sin(angle)的第一個應用——平滑運動this

平滑是指物體一種流暢的運動狀態,與之相反的是機械式的簡單的從0到1再到-1和0的這麼一種狀態。平滑的運動更加趨近與天然的運動狀態,相似水草在水流中的左右搖擺,在擺動的過程當中是有速度的變化的。spa

咱們用Math.sin函數模仿的第一個運動,就是這種相似水草擺動的運動。另外,由於sin函數的值介於[-1,1]之間。因此在實際代碼中須要乘以一個較大的值(也就是振幅,你懂得),使其的擺動看起來明顯一些。水草擺動的以下圖所示,在線演示地址prototype

圖片描述

具體代碼以下rest

//水草類
function Aqu(color, num, amp){
      this.startPoint = [];
      this.endPointX = [];
      this.endPointY = [];
      this.amp = [];
      this.beta = 0;
      this.color = (color == undefined)?"#3b154e":color;
      this.num = (num == undefined)?80:num;
}
       
 Aqu.prototype.init = function(){
       for(var i=0; i<this.num; i++){
           this.startPoint[i] = Math.random()*20 + i*10;
           this.endPointX[i] = this.startPoint[i];
           this.endPointY[i] = canvas.height/1.5 - Math.random()*50;
           this.amp[i] = Math.random()*10 + 40;
       }
   }

Aqu.prototype.draw = function(ctx){
       ctx.save();
       ctx.lineWidth = 14;
       ctx.lineCap = "round";
       ctx.globalAlpha = 0.8;
       ctx.strokeStyle =this.color;
       
       //Math.sin的應用
       this.beta += del*0.0012;
       var l = Math.sin(this.beta);
       
       for(var i=0; i<this.num; i++){
          ctx.beginPath();
          ctx.moveTo(this.startPoint[i], canvas.height);
          
          //週期性改變水草的頂點X座標
          this.endPointX[i] = this.startPoint[i] + l*this.amp[i]
          
          ctx.quadraticCurveTo(this.startPoint[i],canvas.height-120,this.endPointX[i],this.endPointY[i]);
          ctx.stroke();
      }
       ctx.restore();
   }
   
var canvas = document.getElementById('canvas'),
    ctx = canvas.getContext('2d');
    canvas.height = 400;
    canvas.width = 800;
    
    //實例水草
    var oAqu = new Aqu();
    //初始化
    oAqu.init();
       
var oldTime = new Date().getTime(),
    del = null, newTime = null;
       
   (function drawFrmae(){
       window.requestAnimationFrame(drawFrmae);
       ctx.clearRect(0, 0, canvas.width, canvas.height);
           
       newTime = new Date().getTime();
       del = new Date().getTime() - oldTime;
       oldTime = newTime;
       
       oAqu.draw(ctx);
       }())

相比於機械的加減是否是更加的流暢呢?固然,你也經過改變Math.sin(this.beta)中的遞增角度值,控制擺動的速度。

2.線性運動

線性運動是最簡單的一種運動,物體勻速朝某個方向運動,就是線性運動。

圖片描述

原理很簡單,具體代碼請查看linear-vertical-motion.html

<script>
       window.onload = function(){
           var canvas = document.getElementById('canvas'),
                 context = canvas.getContext('2d');
               
           var angle = 0,
               range = 50,
               xspeed = 1,
               yspeed = 0.05;

           var ball = new Ball();
           
           (function drawFrame(){
               window.requestAnimationFrame(drawFrame,canvas);
               context.clearRect(0,0,canvas.width,canvas.height);

               ball.x += xspeed; //水平,沿x軸方向水平運動
               
               if(ball.x > canvas.width + ball.radius){
                   ball.x = -ball.radius;
               }
               //垂直, 因爲angle角度沒發生變化,因此縱座標保持不變
               ball.y = canvas.height/2+Math.sin(angle)*range;
               
              // angle += 0.05; //取消註釋看看發生了什麼?
               ball.draw(context);
           })();
       }
    </script>

其實,這裏若是你把angle += 0.05的註釋取消,你會發現球的運動軌跡就與sin函數的圖像一致了。

3.脈衝運動

除了做用於物體的速度,sin函數仍然能夠做用於物體的大小變化。脈衝運動即是將sin函數運用於物體大小的變化中。

圖片描述

具體代碼以下,詳細代碼請查看plusing-motion.html

window.onload = function(){
            var canvas = document.getElementById('canvas');
            var context  = canvas.getContext('2d');

            var angle = 0,
                range = 0.5,
                speed = 0.05,
                centerScale = 1;

            var ball = new Ball();
                ball.x = canvas.width/2;
                   ball.y = canvas.height/2;

            (function drawFrame(){
                window.requestAnimationFrame(drawFrame,canvas);
                context.clearRect(0,0,canvas.width,canvas.height);
                
                //sin值的變化,致使 ball.scaleX , ball.scaleY屬性變化
                ball.scaleX = ball.scaleY = centerScale + Math.sin(angle)*range;
                angle += speed;

                ball.draw(context);
            })();
        }

由此你應該知道,除了位置屬性,咱們還能夠將sin函數與其餘的屬性相結合,來造成不一樣的運動形式。

相關文章
相關標籤/搜索