使用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也算新手,难免很多地方写的不好及有些错误,请不吝指正,谢谢。

 

 

posted @ 2012-12-01 18:07  三度空间  阅读(4645)  评论(16编辑  收藏  举报