基于HTML5 Canvas和jQuery 的画图工具的实现
簡介
??? HTML5 提供了強大的Canvas元素,使用Canvas并結合Javascript 可以實現一些非常強大的功能。本文就介紹一下基于HTML5 Canvas 的畫圖工具的實現。廢話少說,先看成品:
? 該應用是遵循所見即所得(WYSIWYG, What you see is what you get)原則設計的,它具有以下功能:
1. 可以繪制自由曲線、直線、矩形框和文字;
2. 可以根據需要定義線段和矩形框的顏色和寬度;
3. 你可以需要字體的大小、顏色、字體;
4. 支持undo、redo操作;
5. 支持橡皮擦功能;
6. 支持本地圖片保存功能。
源碼下載?????? 1. 讀者可以去我的GitHub jPainter項目下下載,?????? 2. 或者直接使用git 工具:https://github.com/LuanLouis/jPainter.git
?????? 3. 或者 通過 http://download.csdn.net/detail/u010349169/7748093 下載
開發心得分享
上述功能的實現,難點倒不是很多,值得一提的有以下幾點:
1.? 鼠標按下并移動 事件應該怎樣實現?
2. 怎樣實現所見即所得? 的設計
3. undo redo 的實現原理
4. 畫板信息另存為圖片
鼠標按下并移動 事件應該怎樣實現
????????如果我們在畫板想畫自由曲線,我們需要捕獲鼠標按下并拖動的過程中 拖動的軌跡。那么怎樣捕獲這樣的事件呢? 熟悉javascript 事件的讀者應該知道,鼠標移動事件的句柄是 onmousemove,有的讀者可能認為,可以直接為onmousemove 綁定事件處理函數,從event事件對象的button屬性來判斷是鼠標的哪一個鍵點擊不就行了嗎?代碼如下:
$(function() {$(document).mousemove(function(e){console.log(e.button+" "+e.which);}) });而實際上,上述的代碼運行時,當我們在頁面上無論是點擊鼠標的哪個鍵,都是輸出如下的信息:
從輸出的結果可以看出,結果和我們預期的并不一樣。這是為什么呢?
?原因是:? javascript的事件機制是這樣的,當用戶觸發了事件之后,javascript宿主-瀏覽器會將事件封裝成event對象,然后根據事件的類型對event屬性進行賦值。然后根據event的類型,根據什么類型的事件來調用相應的事件處理函數。舉例來說,如果我們在界面上按下了鼠標的右鍵,那么,瀏覽器會首先創建一個event對象,然后對event屬性賦值,而相應的button會被置為2、which為3表示右鍵被按下;然后javascript 會將此event對象作為參數傳遞給相應的事件處理函數,執行事件處理函數。也就是說,event的button屬性(以及jquery封裝后的which屬性)只有當 click、mousedown,mousup 對應的事件處理函數才有意義。
那么,我們怎樣才能判斷當鼠標移動時,鼠標鍵是否被按下呢?
解決方法:鼠標按下和松開是個過程,我們可以設置一個 flag,在鼠標按下的時候置為true,鼠標松開的時候置為false,然后在鼠標移動的事件處理函數中判斷這個flag,進而可以區分鼠標是否被按下。
假設我們需要在<body> 元素上捕獲 相應的鼠標事件,以下是使用jquery 進行事件處理函數的綁定:
//onmousemove 事件$("body").mousemove(function(e){if(flag){// 鼠標被按下}})//onmousedown事件 $("body").onmousedown(function(e){flag = true; // 事件處理 })//onmouseup事件 $("body").mouseup(function(e){flag = false;// 事件處理 })??????????? 當然,如果讀者有其他的實現方案,還請不吝賜教,共同學習!
怎樣實現所見即所得的設計
?????? 使用Canvas繪圖時,其繪圖是通過javascript控制的,比如,我想繪制一個矩形,應該使用類似以下的代碼:
var c=document.getElementById("myCanvas"); var cxt=c.getContext("2d"); cxt.fillStyle="#FF0000"; cxt.fillRect(0,0,150,75);??????? 但是對于對于可交互的用戶界面,如果想創建一個矩形,應該是通過鼠標在畫板上拖動,然后可以隨時看到我將要畫的矩形的大小、邊框、顏色等等。怎樣讓用戶可以看到動態的效果呢? 當然了,使用canvas 肯定是實現不了的,這里我想到了一個方法,就是使用<DIV> 元素模擬我們需要繪制的矩形,當用戶在拖動鼠標的過程中,使用DIV 顯示矩形的信息,一旦用戶松開鼠標,那么,將此DIV隱藏,根據鼠標的軌跡以及矩形配置,使用javascript繪制在對應的形狀。類似地,繪畫直線和添加文字也是通過HTML偽裝的邏輯:
繪畫直線時,用戶在畫板上拖動并按下鼠標時,動態地顯示出一條使用HTML偽裝的直線,可以隨著用戶鼠標的移動而變化,當用戶松開鼠標時,對應模擬直線的HTML元素隱藏,調用javavscript繪制真正的直線;
添加文字時,這里使用的<textarea>元素 進行模擬文本輸入框,當用戶在畫板上添加文字時,可以拖動鼠標設置輸入框的大小,然后輸入文字,一旦輸入框失去焦點,則隱藏此<textarea> 元素,然后使用javascript繪制相應的文字
undo redo 的實現原理
? ? ? 在介紹 undo? redo 的實現之前,要先講一下canvas的toDataURL()方法。toDataURL()方法將canvas上所繪制的內容轉換成格式png格式圖片,并將圖片通過base64編碼,轉換成形如如:data:image/png;base64,iVBORw0KGg.......?的字符串,用來表示圖片數據。(PS:對此比較困惑的讀者可以自行查找關于HTML 圖片 BASE64 存儲的相關問題,這個知識點還是很重要的)
????? undo redo 的原理實際上很簡單,就是當每執行一次繪畫,則將畫板的內容轉換成base64編碼的字符串,存到緩存數組中去,然后在需要undo 的時候,將畫板清空,再將緩存數組中的最后一次編輯的圖片繪制到畫板上即可。相關的實現細節如下代碼所示:
//undo redovar history =new Array();var cStep = -1;/*** put current canvas to cache*/function historyPush(){cStep++;if (cStep < history.length) { history.length = cStep; }history.push($("#myCanvas").get(0).toDataURL());}/*** function: undo */function undo(){if (cStep >= 0) {cStep--;var tempImage = new Image();tempImage.src = history[cStep];tempImage.onload = function () { ctx.drawImage(tempImage, 0, 0);};}}/*** function: redo*/function redo(){if (cStep <history.length-1) {clearCanvas();cStep++;var tempImage = new Image();tempImage.src = history[cStep];tempImage.onload = function () { ctx.drawImage(tempImage, 0, 0); };}}畫板信息存為圖片
代碼如下:
/*** save canvas content as image*/function saveItAsImage(){var image = $("#myCanvas").get(0).toDataURL("image/png").replace("image/png", "image/octet-stream");//locally savewindow.location.href=image; }源碼下載?????? 1. 讀者可以去我的GitHub jPainter項目下下載,
?????? 2. 或者直接使用git 工具:https://github.com/LuanLouis/jPainter.git
?????? 3. 或者 通過 http://download.csdn.net/detail/u010349169/7748093 下載
-----------------------------------------------------------------------------------------------------------------------------------------
本文源自? http://blog.csdn.net/luanlouis/,如需轉載,請注明出處,謝謝!
總結
以上是生活随笔為你收集整理的基于HTML5 Canvas和jQuery 的画图工具的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微软应用商店的服务器,微软也玩起「快应用
- 下一篇: 怎样入门web前端开发?