可選擇畫筆粗細 顏色的 網頁版繪圖介面 本篇將利用 HTML5 的 canvas 來建立繪圖程式, 實作 畫筆模式 / 橡皮擦模式選擇 線條粗細的 3 階段 ( 粗. 中. 細 ) 設定 從 10 個顏色中選擇線條顏色 等功能, 藉此學習 canvas 的基本操作及事件處置 製作. 撰文 / 小原暢 ( 面白法人 KAYAC) 使用技巧 canvas 元素 JavaScript 製作要點活用 data 屬性的簡單實作使用 jquery 的 delegate() 之事件處置針對圖示等圖像, 使用 SVG 的技巧 支援瀏覽器 / 智慧型手機 IE 9 以上 Firefox 26 以上 Safari 7 以上 Chrome 32 以上 使用的外掛程式 jquery(2.0.3) http://code.jquery.com/jquery-2.0.3.min.js
滑鼠事件的處置 01 首先, 思考一下用滑鼠畫線的操作動作, 為此必須處理 : mousedown mousemove mouseup 等 3 個事件 各個事件中進行的處理如表 01-1 所示 一開始加入的事件處理器只有 mousedown, mousemove mouseup 的事件處理器則是視需要加入 / 刪除 01-1 滑鼠事件種類事件 mousedown mousemove mouseup 內容 初始化路徑 設定路徑起點 加入 mousemove 事件處理器 加入 mouseup 事件處理器 加入路徑 & 沿著路徑描繪 刪除 mousemove 事件處理器 刪除 mouseup 事件處理器 02 mousedown 事件處理器中所進行的處理如下 初始化路徑設定路徑起點加入 mousemove 事件處理器加入 mouseup 事件處理器程式碼如 02-1 所示 首先是以 begingpath() 初始化路徑 在這之後, 以 moveto() 將路徑的起點設定為現在的滑鼠座標 滑鼠的 x 座標 y 座標在這次的情況下是以 evt.pagex, evt.pagey 取得 再來, 加入 mousemove mouseup 事件處理器 02-1 mousedown 事件的處理 (app.js) function handlemousedown(evt) { ctx.beginpath(); ctx.moveto(evt.pagex, evt.pagey); $(document).bind('mousemove', handlemousemove); $(document).bind('mouseup', handlemouseup);
Chapter 2 API 及 Web 應用程式 03 mousemove 事件處理器中進行的處理如下 加入路徑描繪加入之路徑 ( 線段 ) 程式碼如 03-1 所示 03-1 mousemove 事件的處理 (app.js) function handlemousemove(evt) { ctx.lineto(evt.pagex, evt.pagey); ctx.stroke(); 從路徑的起點 ( 或目前為止建立好的路徑終點 ) 開始描繪到現在滑鼠座標為止的線段 請注意, 只執 行 lineto() 不會描繪線條, 要執行 stroke() 才會開始描繪線條 04 04-2 實作好滑鼠事件的狀態 mouseup 事件處理器中進行的處理如下 刪除 mousemove 事件處理器刪除 mouseup 事件處理器程式碼如 04-1 所示 綜合以上步驟, 就會顯示圖 04-2 的樣子 04-1 mouseup 事件的處理 (app.js) function handlemouseup() { $(document).unbind('mousemove', handlemousemove); $(document).unbind('mouseup', handlemouseup); 選擇線條粗細 顏色 05 接著, 來實作變更線條粗細及顏色時的處理 在此利用 data 屬性, 就可以對 DOM 元素加上任意的資料 ( 字串 ) 首先, 準備 05-1 的 HTML 在各按鈕的 div 元素設定 data-size 屬性, 值分別設為 small medium large, 這個最後會附加上選擇線條粗細的功能
05-1 各按鈕的 div 元素 (index.html) <div class="btns"> <div class="btn size small" data-size="small"></div> <div class="btn size medium" data-size="medium"></div> <div class="btn size large" data-size="large"></div> </div> 06 程式 06-1 展示了 JavaScript 程式碼 在 click 事件處理器中, 取得被按下之元素的 data-size 屬性值, 從取得的值來判別哪個按鈕被按下 ( 亦即, 哪個尺寸被選擇 ) 這個方法與 jquery 的 delegate() 併用時特別方便 使用 delegate(), 就可以削減事件處理器的數量, 效能會比較好 反之, 不使用 delegate() 而只準備按鈕數量的事件處理器的話, 程式碼的量會增加而影響效能 06-1 透過使用者的操作動態變更線條粗細 function handlesizeclick() { var size = $(this).attr('data-size'); switch (size) { case 'small' : ctx.linewidth = 5; case 'medium' : ctx.linewidth = 10; case 'large' : ctx.linewidth = 20; default : $(document).delegate('.btn.size', 'click', handlesizeclick); 07 接下來, 我們加入使目前選擇的按鈕醒目顯示的處理 在 JavaScript 中, 當按鈕被按下時, 將按鈕的 data-size 屬性值設定於 body 的資料屬性 data-size 中 07-1 而在 CSS 中, 配合 body 的 data-size 屬性值改變各按鈕的顯示 07-2
Chapter 2 API 及 Web 應用程式 07-1 判別哪個按鈕被按下 function handlesizeclick() { var size = $(this).data('size'); switch (size) { case 'small' : ctx.linewidth = 5; 省略 default : $(document.body).attr('data-size', size); $(document).delegate('.btn.size', 'click', handlesizeclick); 07-2 使被選擇的按鈕醒目顯示 body[data-size="small"], body[data-size="medium"], body[data-size="large"] { /* 醒目顯示的樣式設定 */ 08-1 將變更線條尺寸的處理分離出來 08 function handlesizeclick() { 本步驟著眼於 handleclick 內的處理, 進行的處理大致是以下 3 個 1 取得 data-size 屬性 2 對應取得之資料屬性 data-size, 變更描繪的線條屬性 3 對 body 標籤設定資料屬性 data-size, 使被選擇的按鈕醒目顯示 1 為事件處理, 而 2 和 3 則是變更線條尺寸的邏輯處理 為了提高可維護性, 將它們分離 08-1 setsize($(this).data('size')); function setsize(size) { switch (size) { case 'small' : ctx.linewidth = 5; 省略 default : $(document.body).attr('data-size', size); $(document).delegate('.btn.size', 'click', handlesizeclick);
09 接著是變更線條尺寸的部份, 藉此可進行如 09-1 的初始化處理 到這邊我們來復習一下 利用資料屬性達成簡單的實作 使事件處理器的數量最小化, 提升效能 從事件處理器中將邏輯處理分離出來, 提升可維護性 09-1 初始化處理的例子 setsize('small'); 10 變更線條顏色也一樣 程式碼如 10-1 10-2 所示 10-1 與變更線條顏色的按鈕相關連 (index.html) <div class="palette"> <div class="color" style="background-color: #000;" data-color="#000"></div> <div class="color" style="background-color: #fff;" data-color="#fff"></div> 省略 <div class="color" style="background-color: #f90;" data-color="#f90"></div> <div class="color" style="background-color: #f00;" data-color="#f00"></div> </div> 10-2 改變線條顏色 (JavaScript) function handlecolorclick() { setcolor($(this).data('color')); function setcolor(color) { ctx.strokestyle = color; $(document).delegate('.btn.color', 'click', handlecolorclick); setcolor('#000');