---
# System prepended metadata

title: 'Day8: Fun with HTML5 Canvas'
tags: [JS30]

---

Day8: Fun with HTML5 Canvas
==
###### tags: `JS30` 

CanvasRenderingContext2D 是 HTML5 Canvas API 中的一個關鍵介面，定義了繪圖上下文（drawing context）和相關的繪圖方法
Day8 使用這個來玩玩繪圖
![](https://i.imgur.com/khUN3pk.gif =80%x)


## <font color="#3733FF">介紹</font>
可到官方閱讀使用方法 [CanvasRenderingContext2D ](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D)

CanvasRenderingContext2D 是 CanvasRenderingContext 接口的一個實現，使用 HTMLCanvasElement.getContext() 方法，當一個 canvas 元素被創建時，它的內容被設置為一個空白的 bitmap，通過 CanvasRenderingContext2D 的繪圖方法，開發者可以在這個 bitmap 上繪製各種形狀和圖像，然後通過 canvas 元素顯示出來。

## <font color="#3733FF">屬性</font>
```
strokeStyle：線條的顏色或樣式，可以是 CSS 颜色、渐变或图案。
lineWidth：線條的粗细。
lineCap：線條末端的樣式，可以是 butt（平端）、round（圓端）或 square（方端）。
lineJoin：兩條線條相交時的樣式，可以是 round（圓交）, bevel（斜交）或 miter（尖交）。

ctx.beginPath(): 開始一個新的繪圖路徑。
ctx.moveTo(x, y): 移動畫筆到指定的座標(x,y)。這個方法是用來定義線條的起點。
ctx.lineTo(x, y): 添加一條由當前點到指定座標(x,y)的線段。
ctx.stroke(): 畫出當前的線條。
```

## <font color="#3733FF">初步建置</font>
使用常見屬性定義好想要的樣式，用hsl的漸層色增加畫筆顏色變化
```javascript!
const canvas = document.querySelector('#draw')

const ctx = canvas.getContext('2d')
canvas.width = window.innerWidth
canvas.height = window.innerHeight

ctx.strokeStyle = '#BADA55'
ctx.lineJoin = 'round'
ctx.lineCap = 'round'
ctx.lineWidth = 100

let isDrawing = false
let lastX = 0
let lastY = 0

let hue = 0
let direction = true
```
## <font color="#3733FF">addEventListener</font>
加上 addEventListener ，定義在mousedown事件觸發時，isDrawing才是true，才可以畫圖，記得要更新目前位置
```javascript!
canvas.addEventListener('mousemove',draw)
canvas.addEventListener('mousedown',(e) => {
  isDrawing = true
  lastX = e.offsetX
  lastY = e.offsetY
})
canvas.addEventListener('mouseup',() => isDrawing = false)
canvas.addEventListener('mouseout',() => isDrawing = false)
```

## <font color="#3733FF">Draw function</font>
利用isDrawing 來判斷是否執行函式內容，主要是顏色和移動位置的設定，優化線條寬度的變化，當direction =  true 時，線條寬度會增加，當 direction 的值為 false 時，線條寬度會減少。這樣可以讓線條寬度在一定範圍內來回變化。


```javascript!
function draw(e) {
  if(!isDrawing) return
  // style
  ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`
  ctx.beginPath()
  // start from
  ctx.moveTo(lastX, lastY)
  // go to
  ctx.lineTo(e.offsetX, e.offsetY)
  ctx.stroke()
  lastX = e.offsetX
  lastY = e.offsetY
  hue++

  if (hue >= 360) {
    hue = 0
  }
  if (ctx.lineWidth >= 100 || ctx.lineWidth <= 1) {
    direction = !direction
  }
  if (direction) {
    ctx.lineWidth++
  } else {
    ctx.lineWidth--
  }

}
```
