[Canvas] 使用 JavaScript 實作 canvas 畫筆的功能
畫筆的功能
大家都有玩過小畫家,我們可以使用小畫家的畫筆,輕鬆的畫出一些我們想要的圖案,相當的趣味也非常的方便
畫筆的功後續也演變為一些電子簽證的機制,最近剛好也碰到了一些類似的需求
決定在下方做個製作上的紀錄,下方提供了一個比較陽春的版本當作範例,也是為了方便理解他的製作方式
進入說明
HTML 架構如下所示:
<canvas id="canvas"></canvas>
宣告變數 與 事件監聽
宣告變數
// Canvas DOM 元素
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
//起始點座標
let x1= 0
let y1= 0
// 終點座標
let x2= 0
let y2= 0
事件監聽
如果你剛剛有稍微玩了一下上面的 demo , 你不難發現這個範例所使用的事件監聽,分別是 按下滑鼠 mousedown
、 移動滑鼠 mousemove
與 放開滑鼠 mouseup
而在手機或是行動裝置上則是 按下滑鼠
ontouchstart
、 移動滑鼠ontouchmove
與 放開滑鼠touchend
// 宣告一個 hasTouchEvent 變數,來檢查是否有 touch 的事件存在
const hasTouchEvent = 'ontouchstart' in window ? true : false
// 透過上方的 hasTouchEvent 來決定要監聽的是 mouse 還是 touch 的事件
const downEvent = hasTouchEvent ? 'ontouchstart' : 'mousedown'
const moveEvent = hasTouchEvent ? 'ontouchmove' : 'mousemove'
const upEvent = hasTouchEvent ? 'touchend' : 'mouseup'
// 宣告 isMouseActive 為滑鼠點擊的狀態,因為我們需要滑鼠在 mousedown 的狀態時,才會監聽 mousemove 的狀態
let isMouseActive = false
藉由上方的事件參數,就可以達到我們想要的事件監聽了
canvas.addEventListener(downEvent, function(e){
isMouseActive = true
})
canvas.addEventListener(moveEvent, function(e){
if(mouseAvtive){
return
}
})
canvas.addEventListener(upEvent, function(e){
isMouseActive = false
})
Canvas 畫筆 製作
有了上述的 參數 與 事件監聽 我們就可以開始製作畫筆的功能了,這邊我照著事件順序依依進行說明:
首先我們必須要在 mousedown
的當下,找到當前點擊的座標為起始座標,並設定一些畫出來線條的寬度
canvas.addEventListener(downEvent, function(e){
isMouseActive = true
x1 = e.offsetX
y1 = e.offsetY
ctx.lineWidth = 5 // 線條寬度
ctx.lineCap = 'round' // 線條兩端圓弧
ctx.lineJoin = 'round' // 線條折角圓弧
})
event.offsetX、event.offsetY 滑鼠相對於事件源元素(srcElement)的 X, Y 坐標
接著在 mousemove
中,使用前面得到的起始座標當作起始點,並以 mousemove 中的得到座標當作目標
並且在繪製結束後,使用終點目標來更新其實座標 (使 mousemove 的事件繪圖是保持連貫的)
canvas.addEventListener(moveEvent, function(e){
if(!isMouseActive){
return
}
// 取得終點座標
x2 = e.offsetX
y2 = e.offsetY
// 開始繪圖
ctx.beginPath()
ctx.moveTo(x1, y1)
ctx.lineTo(x2, y2)
ctx.stroke()
// 更新起始點座標
x1 = x2
y1 = y2
})
這樣基本畫筆的功能就算是完成了,十分容易
完整的代碼如下:
// Canvas DOM 元素
const canvas = document.getElementById('canvas')
const ctx = canvas.getContext('2d')
//起始點座標
let x1= 0
let y1= 0
// 終點座標
let x2= 0
let y2= 0
// 宣告一個 hasTouchEvent 變數,來檢查是否有 touch 的事件存在
const hasTouchEvent = 'ontouchstart' in window ? true : false
// 透過上方的 hasTouchEvent 來決定要監聽的是 mouse 還是 touch 的事件
const downEvent = hasTouchEvent ? 'ontouchstart' : 'mousedown'
const moveEvent = hasTouchEvent ? 'ontouchmove' : 'mousemove'
const upEvent = hasTouchEvent ? 'touchend' : 'mouseup'
// 宣告 isMouseActive 為滑鼠點擊的狀態,因為我們需要滑鼠在 mousedown 的狀態時,才會監聽 mousemove 的狀態
let isMouseActive = false
canvas.addEventListener(downEvent, function(e){
isMouseActive = true
})
canvas.addEventListener(downEvent, function(e){
isMouseActive = true
x1 = e.offsetX
y1 = e.offsetY
ctx.lineWidth = 5
ctx.lineCap = 'round'
ctx.lineJoin = 'round'
})
canvas.addEventListener(moveEvent, function(e){
if(!isMouseActive){
return
}
// 取得終點座標
x2 = e.offsetX
y2 = e.offsetY
// 開始繪圖
ctx.beginPath()
ctx.moveTo(x1, y1)
ctx.lineTo(x2, y2)
ctx.stroke()
// 更新起始點座標
x1 = x2
y1 = y2
})
canvas.addEventListener(upEvent, function(e){
isMouseActive = false
})