先來看動畫效果:javascript
這個動畫看起來有點難,但其實要比想象中的簡單。java
它只是平移和旋轉的簡單合成,下面大致分析一下。編程
要跟隨鼠標移動,首先就要獲取鼠標的位置。canvas
能夠給畫布綁定mousemove事件,這樣拿到鼠標相對於頁面的絕對位置(pageX,pageY),再減去畫布自身的偏移量,就能夠獲得鼠標相對畫布的位置。核心代碼是:瀏覽器
canvas.addEventListener('mousemove', event => {
mouse.x = event.pageX - canvas.offsetLeft
mouse.y = event.pageY - canvas.offsetTop
})
複製代碼
知道鼠標和箭頭的位置信息,就能夠算出一些有用的值,好比兩者水平和垂直距離。微信
根據三角函數tan的反函數就能夠求出相應角度。Math對象中有兩個反正切函數atan和atan2。其中比較好用的倒是不太顯眼的atan2。函數
var dx = mouse.x - arrow.x
var dy = mouse.y - arrow.y
var angle = Math.atan2(dy, dx)
複製代碼
使用requestAnimationFrame(canvas動畫常規操做),實時更新箭頭角度,就能夠作出跟隨鼠標旋轉的動畫啦。動畫
;(function drawFrame() {
window.requestAnimationFrame(drawFrame)
context.clearRect(0, 0, canvas.width, canvas.height)
var dx = mouse.x - arrow.x
var dy = mouse.y - arrow.y
var angle = Math.atan2(dy, dx)
arrow.angle = angle
arrow.draw(context)
})();
複製代碼
drawFrame做爲瀏覽器下次重繪前的回調函數,每一幀都清空畫布,而後畫出特定角度的箭頭。效果以下:ui
點擊查看效果spa
要實現平移動畫,只須要勻速地修改箭頭地位置。
arrow.x += vx
arrow.y += vy
複製代碼
這裏的難點在於如何計算水平速度和垂直速度。咱們假設鼠標移動速度是v,那麼三者的關係應該知足於:
所以,角度剛纔已經算出來了,那麼根據三角函數有:
vx = Math.cos(angle) * v
vy = Math.sin(angle) * v
複製代碼
不考慮旋轉的跟隨移動效果以下:
一邊朝着鼠標移動,一邊指向鼠標,就能實現文章開頭的效果。
注意代碼里加了下面的判斷,這是爲了防止出現平移動畫的震盪bug。
if (dx * dx + dy * dy < v * v) {
vx = 0
vy = 0
} else {
vx = Math.cos(angle) * v
vy = Math.sin(angle) * v
}
複製代碼
能夠分析下出現震盪的緣由。好比箭頭距離鼠標1像素,下一幀加上速度2後,距離變成了-1,朝向變成了反方向。再下一幀,距離又變成了1,而後震盪不停。這裏的解決辦法比較生硬,一旦距離小於v(速度就是一幀內移動的距離)時,直接再也不移動了。
這個動畫很常見,參考書目2裏面也提到了,但沒想到原理卻出乎意料的簡單。
另外飛機遊戲中,敵機自動向你移動也是一樣的邏輯。
本文只是大致分析了一下原理,但願有所幫助。
完。
2019年底,本人立了個flag,2020年要研究透canvas動畫技術。
(圖中二維碼是個人惟一微信號,若有掘友想加的,麻煩備註下【掘金】哈。)
在這個系列,我想寫一些常見動畫知識,本文是第2篇,篇幅可能會長短不一。更多的請查看個人我的主頁,或者《系列目錄》。
由於篇幅問題,根據以往的經驗,贊數不會太多,畢竟你們都喜歡給那種短期看不完的文章點贊。嗯,我好像也是這樣。^_^
其實寫文章,主要仍是給本身看的,算是自我進步的一個見證吧。抱着這種心態也許能好些。
另外關於canvas技術,我目前完整看完了3本書。算是過了基礎一關。
本系列一些文章可能會參考裏面的知識體系,對於一些屬於領域共識知識,若有局部雷同,只能說:「本身憑本事學來的,怎能算抄襲。。。」。
開玩笑了,想法來源能提一句仍是要提一句的。特別喜歡《精英日課》文章裏的一段話:
至於文章內容,canvas的API,本系列可能不會準備逐條介紹了,還請初學的童鞋見諒哈。MDN都有的,挺詳細的。同時,文章中遇到的仍是會簡單提下。主要核心是闡述一些技巧和原理層面的知識我的理解吧。另外也打算分析一些codepen上炫酷動畫的實現原理,若是有時間可能會分析幾個動畫引擎,固然都是2D的。
再次感謝你閱讀到這裏。下一篇文章見。