Day 8 - HTML Canvas


Posted by hoyi-23 on 2021-07-26

這次的練習會運用到 HTML Canvas Graphics

今天我想自己練習來作一個超級簡易版小畫家,效果包含:

  1. 顏色
  2. 筆刷粗細
  3. 橡皮擦
  4. 放上貼圖(構想)

HTML Canvas

HTML Canvas 會提供一個畫布空間,需要使用到JavaScript來作畫。

如何使用?

Canvas為一個正方形的區塊,預設就是空白的、沒有border。
HTML:

<canvas id="myCanvas" width="200" height="100"></canvas>

JavaScript:
取得 Canvas 的渲染環境及其繪圖函數

const canvas = document.querySelector('#myCanvas');
const ctx = canvas.getContext('2d');

設定 Canvas滿版

但放上去後發現就算更改的寬度和長度,還是無法讓畫布滿版、自適應整個螢幕。

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

基本content樣式設定

前面提到 canvas 就是一個空白的畫布,填上東西靠的是content。
通常會宣告為ctx
我們可以先對ctx最一些基礎的設定(例如: 筆刷大小/ 顏色等)

ctx.strokeStyle = '#bada55';  // 筆觸顏色
ctx.lineJoin = 'round';  // 兩條線交匯處產生 "圓形" 邊角
ctx.lineCap = 'round';  // 筆觸預設為 "圓形"
ctx.lineWidth = 1;  // 筆頭寬度

let isDrawing = false;  // 是否 mousedown下筆狀態

/* 起點座標 */
let lastX = 0;
let lastY = 0;
  1. 管理狀態:save(), restore()
  2. 變形:scale(), rotate(), translate(), transform(), setTransform()
  3. 畫面組成:globalAlpha, globalCompositionOperation
  4. 色彩與風格: strokeStyle,fillStyle,createLinearGradient(),createRadialGradient(), createPattern()
  5. 線條邊角及組合:lineWidth, lineCap, lineJoin, miterLimit
  6. 陰影:shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor
  7. 方形繪出:clearRect(), fillRect(), strokeRect()
  8. 路徑API:beginPath(), closePath(), moveTo(), lineTo(), quadraticCurveTo(), bezierCurveTo(), arcTo(), rect(), arc(), fill(), stroke(), clip(), isPointInPath()
  9. 焦點管理:drawFocusRing()
  10. 文字:font, textAlien, textBaseline, fillText(), strokeText(), measureText()
  11. 影像:drawImage(), createImageData(), getImageData(), putImageData()

繪圖函數與下筆(mousedown)監聽

重點:

  1. 監聽: 只有在 mousedown 時才會畫圖,mouseup & mouseout 不會。
  2. 要試訂下筆起始點,不然起始點的預設是左上角的(0,0),按照預設的話會從左上角連到下筆的位置。
canvas.addEventListener('mouseup', () => isDrawing = false);
canvas.addEventListener('mouseout', () => isDrawing = false);
canvas.addEventListener('mousedown', (e) => {
    isDrawing = true; 
    [lastX, lastY] = [e.offsetX, e.offsetY]; // 設定起始點
});

canvas.addEventListener('mousemove', draw); 

// 繪製函數;在 mousemove 的時候使用
function draw(e) {
    if(!isDrawing) return;  // 沒有允許繪製即退出

    /* 繪製路線 Setting */
    ctx.beginPath();  // 產生一個新路徑,產生後再使用繪圖指令來設定路徑。
    ctx.moveTo(lastX, lastY);  // 設定起點
    ctx.lineTo(e.offsetX, e.offsetY);  // 設定終點
    ctx.stroke();  // 依照設定開始繪製

    [lastX, lastY] = [e.offsetX, e.offsetY];  // 位置更新

    //當目前路徑為空(例如接著呼叫beginPath()完後)或是在一個新畫布上,不論為何,第一個路徑繪圖指令總是moveTo();因為每當重設路徑後,你幾乎都會需要設定繪圖起始點。

功能: 顏色

顏色使用 input type="color"
去監聽它的改變在動態寫入value

功能: 粗細

粗細的部分我已經寫好固定提供五個大小
五個圈圈搭被dataset,利用forEach 去監聽每個圈圈是否被點擊,點擊後動態寫入數值。


#canvas







Related Posts

Leetcode 刷題 pattern - Bitwise XOR

Leetcode 刷題 pattern - Bitwise XOR

輸入資料 是否為自然數的 判斷演算法

輸入資料 是否為自然數的 判斷演算法

分辨 Slice()、Split()、Splice()

分辨 Slice()、Split()、Splice()


Comments