使用HTML5+Singalr搭建多機協同畫板(一)


雖然,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也算新手,難免很多地方寫的不好及有些錯誤,請不吝指正,謝謝。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM