【canvas】箭頭跟隨鼠標移動的動畫原理

先來看動畫效果:javascript

這個動畫看起來有點難,但其實要比想象中的簡單。java

它只是平移和旋轉的簡單合成,下面大致分析一下。編程

1. 鼠標位置

要跟隨鼠標移動,首先就要獲取鼠標的位置。canvas

能夠給畫布綁定mousemove事件,這樣拿到鼠標相對於頁面的絕對位置(pageX,pageY),再減去畫布自身的偏移量,就能夠獲得鼠標相對畫布的位置。核心代碼是:瀏覽器

canvas.addEventListener('mousemove', event => {
  mouse.x = event.pageX - canvas.offsetLeft
  mouse.y = event.pageY - canvas.offsetTop
})
複製代碼

2. 鼠標相對於箭頭的方向

知道鼠標和箭頭的位置信息,就能夠算出一些有用的值,好比兩者水平和垂直距離。微信

根據三角函數tan的反函數就能夠求出相應角度。Math對象中有兩個反正切函數atan和atan2。其中比較好用的倒是不太顯眼的atan2。函數

var dx = mouse.x - arrow.x
var dy = mouse.y - arrow.y
var angle = Math.atan2(dy, dx)
複製代碼

3. 旋轉動畫

使用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

4. 平移動畫

要實現平移動畫,只須要勻速地修改箭頭地位置。

arrow.x += vx
arrow.y += vy
複製代碼

這裏的難點在於如何計算水平速度和垂直速度。咱們假設鼠標移動速度是v,那麼三者的關係應該知足於:

所以,角度剛纔已經算出來了,那麼根據三角函數有:

vx = Math.cos(angle) * v
vy = Math.sin(angle) * v
複製代碼

不考慮旋轉的跟隨移動效果以下:

點擊查看效果

5. 最終效果

一邊朝着鼠標移動,一邊指向鼠標,就能實現文章開頭的效果。

點此查看效果

注意代碼里加了下面的判斷,這是爲了防止出現平移動畫的震盪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本書。算是過了基礎一關。

1.《HTML5 Canvas核心技術》

2.《HTML5+JavaScript動畫基礎》

3.《WebGL編程指南》

本系列一些文章可能會參考裏面的知識體系,對於一些屬於領域共識知識,若有局部雷同,只能說:「本身憑本事學來的,怎能算抄襲。。。」。

開玩笑了,想法來源能提一句仍是要提一句的。特別喜歡《精英日課》文章裏的一段話:

至於文章內容,canvas的API,本系列可能不會準備逐條介紹了,還請初學的童鞋見諒哈。MDN都有的,挺詳細的。同時,文章中遇到的仍是會簡單提下。主要核心是闡述一些技巧和原理層面的知識我的理解吧。另外也打算分析一些codepen上炫酷動畫的實現原理,若是有時間可能會分析幾個動畫引擎,固然都是2D的。

再次感謝你閱讀到這裏。下一篇文章見。

相關文章
相關標籤/搜索