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

老姚發表於2020-01-01

先來看動畫效果:

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

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

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

1. 滑鼠位置

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

可以給畫布繫結mousemove事件,這樣拿到滑鼠相對於頁面的絕對位置(pageX,pageY),再減去畫布自身的偏移量,就可以得到滑鼠相對畫布的位置。核心程式碼是:

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

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

知道滑鼠和箭頭的位置資訊,就可以算出一些有用的值,比如二者水平和垂直距離。

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

根據三角函式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作為瀏覽器下次重繪前的回撥函式,每一幀都清空畫布,然後畫出特定角度的箭頭。效果如下:

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

點選檢視效果

4. 平移動畫

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

arrow.x += vx
arrow.y += vy
複製程式碼

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

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

因此,角度剛才已經算出來了,那麼根據三角函式有:

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

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

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

點選檢視效果

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動畫技術。

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

(圖中二維碼是我的唯一微訊號,如有掘友想加的,麻煩備註下【掘金】哈。)

在這個系列,我想寫一些常見動畫知識,本文是第2篇,篇幅可能會長短不一。更多的請檢視我的個人主頁,或者《系列目錄》

因為篇幅問題,根據以往的經驗,贊數不會太多,畢竟大家都喜歡給那種短時間看不完的文章點贊。嗯,我好像也是這樣。^_^

其實寫文章,主要還是給自己看的,算是自我進步的一個見證吧。抱著這種心態也許能好些。

另外關於canvas技術,我目前完整看完了3本書。算是過了基礎一關。

1.《HTML5 Canvas核心技術》

2.《HTML5+JavaScript動畫基礎》

3.《WebGL程式設計指南》

本系列一些文章可能會參考裡面的知識體系,對於一些屬於領域共識知識,如有區域性雷同,只能說:“自己憑本事學來的,怎能算抄襲。。。”。

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

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

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

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

相關文章