昨天介紹了可以追蹤手位置的套件,今天用來做一個刮刮樂效果吧!
要實作刮刮樂效果,需要兩個 Canvas
,其中一個是最後想呈現出來的結果,另一個則需要覆蓋在上方,當尚未刮除的時的背景。所以一開始的時候我們先把兩個都初始化,在背景的我們直接就單純顯示一串文字就可以結束
initialBgCanvas() {
const canvas = this.$refs.bgCanvas
const context = canvas.getContext('2d')
context.font = '30px Microsoft JhengHei, PMingLiU, sans-serif'
context.fillText('恭喜獲得信義區豪宅', 100, 180)
}
在前景的部分,我們先將畫布填滿顏色,當作尚未刮除時的背景,而在這邊有使用到了 globalCompositeOperation
,一般來說,如果我們在舊畫布上繪製東西的話,是會直接覆蓋在舊畫布上面,而這個屬性可以讓我們選擇我們需要使用哪種方式讓這兩個東西混合。MDN 的示意圖介紹的蠻清楚的。
而因為我們的目標是在畫筆移動的時候,顯示出背景的區域,所以就是使用 destination-out
initialFgCanvas() {
const canvas = this.$refs.fgCanvas
const context = canvas.getContext('2d')
context.fillStyle = 'silver'
context.fillRect(0, 0, 450, 380)
context.globalCompositeOperation = 'destination-out'
}
接著在實際做出刮除的效果,因為我們希望在移動的時候就直接刮除,所以要在前景監聽到 mousemove
,並且用獲得的位置去繪製一個圓形,這邊使用了 arc
,前面兩個參數是圓心所在位置,第三個是半徑,四跟五是起始角度跟結束角度,我們因為是要直接畫一個圓出來所以就不特別調整。
handleMousemove(event) {
const canvas = this.$refs.fgCanvas
const context = canvas.getContext('2d')
const x = event.offsetX
const y = event.offsetY
context.beginPath()
context.arc(x, y, 20, 0, Math.PI * 2)
context.fill()
}
一切順利後成果應該會像這樣
基本的做完之後,我們就可以跟昨天介紹到的 handtrack
做整合了,
昨天我們是將偵測到的位置直接繪製上去,今天我們會需要用到詳細偵測到的數值, predictions
會回傳一串被偵測到的手部,但因為我們上次設定了最多只有一,所以這邊直接使用第一個,而bbox
則是可以獲取到框出來的 x、y、寬、高,所以我們就可以拿到手部正中央的位置
model.detect(video).then(predictions => {
model.renderPredictions(predictions, canvas, context, video)
if (predictions.length) {
const [x, y, width, height] = predictions[0].bbox
this.dispatchEvent(x + width / 2, y + height / 2)
}
requestAnimationFrame(this.runDetection)
})
接著我們使用拿到的位置去模擬滑鼠移動的事情,新建一個 mousemove
事件,並且記得將剛剛算出來的位置加上去,接著就是發送事件
dispatchEvent(x, y) {
const event = new Event('mousemove')
event.offsetX = x
event.offsetY = y
this.$refs.fgCanvas.dispatchEvent(event)
}
這樣就大功告成囉
今天做了一個追蹤手部的刮刮樂,其實這應該可以拿來做現場互動裝置的應用,就看大家如何使用囉,能夠在瀏覽器上面直接使用影像辨識模型對於做一些實驗性質的東西真的很方便呢!明天見囉~