做法
建立一個 App
物件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class App { private canvas: HTMLCanvasElement;
private ctx: CanvasRenderingContext2D;
private rectangle: Element;
private ellipse: Element;
private selectedObject: Element | null = null;
constructor() { } }
new App();
|
初始化一個 canvas
畫布,並使用 getContext
方法取得渲染環境和繪圖函式。
1 2 3 4
| constructor() { this.canvas = document.getElementById('canvas') as HTMLCanvasElement; this.ctx = this.canvas.getContext('2d') as CanvasRenderingContext2D; }
|
監聽畫布,並建立一個 handleCanvasClick
處理器。
1 2 3 4 5 6 7 8
| constructor() { this.canvas.addEventListener('click', (e) => this.handleCanvasClick(e)); }
handleCanvasClick(e: MouseEvent) { }
|
使用 ctx
提供的繪圖函式繪製一個矩形。
1 2 3 4 5
| handleCanvasClick(e: MouseEvent) { const x = e.offsetX; const y = e.offsetY; this.ctx.strokeRect(x, y, 100, 100); }
|
使用 ctx
提供的繪圖函式繪製一個橢圓形。
1 2 3 4 5
| handleCanvasClick(e: MouseEvent) { this.ctx.beginPath(); this.ctx.ellipse(x, y, 75, 100, Math.PI / 2, 0, 2 * Math.PI); this.ctx.stroke(); }
|
新增 index.html
檔。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style type="text/css"> html, body { align-items: center; display: flex; height: 100%; justify-content: center; } #canvas { border: 1px solid black; border-radius: 8px; box-sizing: border-box; } .object { align-items: center; border: 1px solid black; border-radius: 8px; box-sizing: border-box; cursor: pointer; display: flex; height: 100px; justify-content: center; text-align: center; user-select: none; width: 100px; } .object:not(:last-child) { margin: 0 12px 12px 0; } .object.selected { border: 2.5px solid black; } </style> </head> <body> <div style="display: flex;"> <div style="display: flex; flex-direction: column;"> <div class="object" id="rectangle">Rectangle</div> <div class="object" id="ellipse">Ellipse</div> </div> <canvas height="660" width="660" id="canvas"></canvas> </div> <script src="dist/main.js"></script> </body> </html>
|
實作不同物件的處理器,以選取工具並繪製指定的圖形。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| class App { private canvas: HTMLCanvasElement;
private ctx: CanvasRenderingContext2D;
private rectangle: Element;
private ellipse: Element;
private selectedObject: Element | null = null;
constructor() { this.canvas = document.getElementById('canvas') as HTMLCanvasElement; this.ctx = this.canvas.getContext('2d') as CanvasRenderingContext2D; this.rectangle = document.getElementById('rectangle') as Element; this.ellipse = document.getElementById('ellipse') as Element; this.init(); }
init() { this.canvas?.addEventListener('click', (e) => this.handleCanvasClick(e)); this.rectangle?.addEventListener('click', (e) => this.handleRectangleClick(e)); this.ellipse?.addEventListener('click', (e) => this.handleEllipseClick(e)); }
handleCanvasClick(e: MouseEvent) { const rect = this.canvas?.getBoundingClientRect() as DOMRect; const x = e.clientX - rect.left; const y = e.clientY - rect.top; switch (this.selectedObject?.id) { case 'rectangle': this.ctx.strokeRect(x, y, 100, 100); break; case 'ellipse': this.ctx.beginPath(); this.ctx.ellipse(x, y, 75, 100, Math.PI / 2, 0, 2 * Math.PI); this.ctx.stroke(); break; default: break; } this.clearSelection(); }
handleRectangleClick(e: Event) { const el = e.target as Element; this.toggleSelection(el); }
handleEllipseClick(e: Event) { const el = e.target as Element; this.toggleSelection(el); }
toggleSelection(el: Element) { const { classList } = el; if (classList.contains('selected')) { this.clearSelection(); return; } this.clearSelection(); classList.add('selected'); this.selectedObject = el; }
clearSelection() { Array.from(document.getElementsByClassName('object')).forEach((el) => el.classList.remove('selected')); this.selectedObject = null; } }
new App();
|
程式碼
參考資料