[Canvas] 使用 JavaScript 實作 canvas 畫筆的功能

[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
})

Facebook 功能: