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-- } } ```