在上一節咱們介紹了canvas動畫中有關三角函數的內容,以及一個跟隨鼠標旋轉的箭頭動畫。這一節主要介紹三角函數的波形運動。包括:html
平滑運動canvas
線性運動bash
脈衝運動dom
sin函數的波形想必騷年們不會感到陌生,其圖形以下所示:函數
若是想要取得sin
函數在[0, 2π]之間的值,非連續的狀況下,能夠這樣估算。動畫
for(var angle=0; angle<Math.PI*2; angle+=0.1){ console.log(Math.sin(angle)); //打印出角度對應的sin值 }
首先介紹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)中的遞增角度值,控制擺動的速度。
線性運動是最簡單的一種運動,物體勻速朝某個方向運動,就是線性運動。
原理很簡單,具體代碼請查看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函數的圖像一致了。
除了做用於物體的速度,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函數與其餘的屬性相結合,來造成不一樣的運動形式。