雖然,HTML5出來好久了,但是,直到最近才開始學習。我就把最近的一些學習心得,通過這篇文章分享一下。

這個小例子使用Singalr作為底層通信的基礎,與服務器進行交互。畫板則使用Html5的canvas來實現。這一部分就先講前端的部分。
1. 新建一個Javascript文件,這里叫做jDraw.js
jDraw.js
1 (function ($) { 2 var methods = {}; 3 $.fn.jDraw = function (method) { 4 if (methods[method]) { 5 return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); 6 } else if (typeof method === 'object' || !method) { 7 return methods.init.apply(this, arguments); 8 } else { 9 $.error('Method ' + method + ' does not exist on DrawJS'); 10 } 11 }; 12 })(jQuery);
2. 我們為 jDraw.js 中的methods 添加一些方法,包括獲取監控鼠標事件,以及各種畫圖功能的方法:
1 var methods = { 2 init: function (options) { 3 //初始化配置 4 var settings = { 5 backgroundColor: '#fff', 6 lineColor: '#bb2646', 7 drawType: 'pen' 8 }; 9 settings = $.extend(settings, options); 10 return this.each(function () { 11 var $this = $(this); 12 var data = $this.data('jDraw'); 13 if (!data) { 14 $(this).data('jDraw', { 15 target: $this, 16 jDraw: { 17 firstCoords: { X: -1, Y: -1 }, 18 lastCoords: { X: -1, Y: -1 }, 19 coords: { X: -1, Y: -1 } 20 }, 21 settings: settings 22 }); 23 } 24 $this.bind('mouseenter.jDraw', methods.mouseenter); 25 $this.bind('mousedown.jDraw', methods.mousedown); 26 $this.bind('mousemove.jDraw', methods.mousemove); 27 $this.jDraw('clear'); 28 }); 29 }, 30 destroy: function () { 31 return this.each(function () { 32 $(window).unbind('.jDraw'); 33 data.jDraw.remove(); 34 $this.removeData('jDraw'); 35 $(window).unbind('mousemove.jDraw', methods.enter); 36 $(window).unbind('mousedown.jDraw', methods.mousedown); 37 $(window).unbind('mousemove.jDraw', methods.mousemove); 38 }) 39 }, 40 mousedown: function (args) { 41 var $this = $(this); 42 var data = $this.data('jDraw').jDraw; 43 var settings = $this.data('jDraw').settings; 44 data.firstCoords.X = args.offsetX; 45 data.firstCoords.Y = args.offsetY; 46 }, 47 mousemove: function (args) { 48 var $this = $(this); 49 var data = $this.data('jDraw').jDraw; 50 var settings = $this.data('jDraw').settings; 51 data.coords.X = args.offsetX; 52 data.coords.Y = args.offsetY; 53 data.lastCoords.X = data.coords.X; 54 data.lastCoords.Y = data.coords.Y; 55 }, 56 mouseenter: function (args) { 57 var $this = $(this); 58 var data = $this.data('jDraw').jDraw; 59 data.lastCoords.X = args.offsetX; 60 data.lastCoords.Y = args.offsetY; 61 }, 62 clear: function (options) { 63 //清除畫布的方法 64 }, 65 setDrawType: function (drawType) { 66 var $this = $(this); 67 var settings = $this.data('jDraw').settings; 68 settings.drawType = drawType; 69 }, 70 setLineColor: function (color) { 71 var $this = $(this); 72 var settings = $this.data('jDraw').settings; 73 settings.lineColor = color; 74 }, 75 pen: function (data) { 76 //實現畫筆的方法 77 }, 78 brush: function (data) { 79 //實現刷子的方法 80 }, 81 rect: function (data) { 82 //實現畫矩形的方法 83 }, 84 circle: function (data) { 85 //實現畫圓的方法 86 }, 87 text: function (data) { 88 //實現文本的方法 89 }, 90 pic: function (data) { 91 //實現在畫布上顯示圖片的方法 92 }, 93 cut: function (data) { 94 //實現裁剪的方法 95 }, 96 zoom: function (data) { 97 //實現縮放功能 98 }, 99 selectImg: function (data) { 100 //實現區域搜索功能 101 } 102 };
3. 當然,現在是不支持移動設備上的, 為了可以在移動設備上運行,我們還得處理移動設備上的touch事件:
1 //在jDraw.js中加入這幾行代碼,用來判斷是否移動設備 2 var isPad = false; 3 if (navigator.userAgent.match(/mobile/i)) 4 isPad = true;
4. 為jDraw.js 中的 methods 增加移動設備上的touch事件監控:
1 init: function (options) { 2 //...省略... 3 return this.each(function () { 4 //...省略... 5 if (isPad) { 6 $this.bind('touchstart.jDraw', methods.touchstart); 7 $this.bind('touchenter.jDraw', methods.touchenter); 8 $this.bind('touchmove.jDraw', methods.touchmove); 9 $this.bind('touchend.jDraw', methods.touchend); 10 } else { 11 $this.bind('mouseenter.jDraw', methods.mouseenter); 12 $this.bind('mousedown.jDraw', methods.mousedown); 13 $this.bind('mousemove.jDraw', methods.mousemove); 14 } 15 $this.jDraw('clear'); 16 }); 17 },
5. 相應的,我們也要更改回收的方法:
1 destroy: function () { 2 return this.each(function () { 3 $(window).unbind('.jDraw'); 4 data.jDraw.remove(); 5 $this.removeData('jDraw'); 6 if (isPad) { 7 $(window).unbind('touchstart.jDraw', methods.touchstart); 8 $(window).unbind('touchenter.jDraw', methods.touchenter); 9 $(window).unbind('touchmove.jDraw', methods.touchmove); 10 $(window).unbind('touchend.jDraw', methods.touchend); 11 } else { 12 $(window).unbind('mousemove.jDraw', methods.enter); 13 $(window).unbind('mousedown.jDraw', methods.mousedown); 14 $(window).unbind('mousemove.jDraw', methods.mousemove); 15 } 16 }) 17 }
6. 我們增加了 touchstart, touchenter, touchmove, touchend 四個方法來監控用戶在移動設備上的觸摸事件,下面為四個方法的具體實現:
1 touchstart: function (args) { 2 $this = $(this); 3 isDraw = true; 4 var event = args.originalEvent.targetTouches[0]; 5 var data = $this.data('jDraw').jDraw; 6 data.firstCoords.X = args.pageX; 7 data.firstCoords.Y = args.pageY; 8 data.lastCoords.X = args.offsetX; 9 data.lastCoords.Y = args.offsetY; 10 }, 11 touchenter: function (args) { 12 $this = $(this); 13 var event = args.originalEvent.targetTouches[0]; 14 var data = $this.data('jDraw').jDraw; 15 data.lastCoords.X = args.pageX; 16 data.lastCoords.Y = args.pageY; 17 }, 18 touchmove: function (args) { 19 var $this = $(this); 20 var data = $this.data('jDraw').jDraw; 21 var settings = $this.data('jDraw').settings; 22 var event = args.originalEvent.targetTouches[0]; 23 data.coords.X = args.offsetX; 24 data.coords.Y = args.offsetY; 25 } 26 data.lastCoords.X = data.coords.X; 27 data.lastCoords.Y = data.coords.Y; 28 }, 29 touchend: function (args) { 30 var event = args.originalEvent; 31 if (event.changedTouches) 32 isDraw = false; 33 }
7. 上面的 isDraw 是定義為全局的變量(全局變量是魔鬼。。。),用來判別移動設備上是否畫上。
8. 上面提供的畫圖方法很多,這里提供個畫線的方法,也就是實現methods中的pen這個方法:
1 pen: function (data) { 2 var $this = $(this); 3 var context = $this.get(0).getContext('2d'); 4 //實現鉛筆代碼... 5 context.strokeStyle = data.Color; 6 context.lineWidth = 5; 7 context.beginPath(); 8 context.moveTo(data.From.X, data.From.Y); 9 context.lineTo(data.To.X, data.To.Y); 10 context.fill(); 11 context.stroke(); 12 context.closePath(); 13 $this.trigger('pen.jDraw', data); 14 }
9. 其他方法的只要相應的實現就可以了,這里不再累贅。那什么時候執行 pen 這個方法呢? 是在鼠標按住並且移動的時候,那我們必須監控鼠標是否被按住,在jDraw.js中添加監控鼠標是否按住的方法:
1 //for PC 2 var leftButtonDown = false; 3 //for Pad or Mobile 4 var isDraw = false; 5 6 $(document).mousedown(function (e) { 7 if (e.which === 1) 8 leftButtonDown = true; 9 }); 10 $(document).mouseup(function (e) { 11 if (e.which === 1) 12 leftButtonDown = false; 13 }); 14 15 function tweakMouseMoveEvent(e) { 16 if ($.browser.msie && !(document.documentMode >= 9) && !event.button) { 17 leftButtonDown = false; 18 } 19 if (e.which === 1 && !leftButtonDown) 20 e.which = 0; 21 };
10. 在 mousemove 和 touchmove 中實現畫圖功能,(對於定點繪圖,則分別實現在mousedown 和 touchenter 中):
1 mousemove: function (args) { 2 tweakMouseMoveEvent(args); 3 var $this = $(this); 4 var data = $this.data('jDraw').jDraw; 5 var settings = $this.data('jDraw').settings; 6 data.coords.X = args.offsetX; 7 data.coords.Y = args.offsetY; 8 //過濾掉定點繪圖的方法 9 if (args.which == 1 && settings.drawType != 'text' && settings.drawType != 'pic') { 10 //drawType為各種方法名,如 pen, brush等 11 $this.jDraw(settings.drawType, { 12 From: { 13 X: data.lastCoords.X, 14 Y: data.lastCoords.Y 15 }, To: { 16 X: data.coords.X, 17 Y: data.coords.Y 18 }, First: { 19 X: data.firstCoords.X, 20 Y: data.firstCoords.Y 21 }, 22 Color: settings.lineColor, 23 DrawType: settings.drawType 24 }); 25 } 26 data.lastCoords.X = data.coords.X; 27 data.lastCoords.Y = data.coords.Y; 28 }
這樣,就把各種繪圖方法跟鼠標事件綁定。
12. 頁面中如何使用該文件,首先,要引入 jquery.js 和 jDraw.js :
1 <script src="../Scripts/jquery-1.6.4.min.js" type="text/javascript"></script> 2 <script src="../Scripts/jDraw.js" type="text/javascript"></script>
13. 頁面中創建canvas對象:
1 <canvas id="whiteBoard"> 2 <p>Unsupported brower</p> 3 </canvas>
14. 簡單的使用:
1 $('#whiteBoard').jDraw().bind('pen.jDraw', function (event, args) { 2 args.Color = drawColor; 3 args.DrawType = dt; 4 $('#whiteBoard').jDraw('pen', args); 5 });
下一篇將結合Singalr,實現多機協同畫板等功能。
初接觸HTML5,Javascript也算新手,難免很多地方寫的不好及有些錯誤,請不吝指正,謝謝。
