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

NO IMAGE

先來看動畫效果:

【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的。

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

相關文章

阿里面試官讓我講講Unicode,我講了3秒說沒了,面試官說你可真菜

網頁設計中最常用的5種配圖

[前端]實戰年終盤點

一杯茶的時間,上手Docker