Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Online Whiteboard using HTML5 and SignalR

0.00/5 (No votes)
5 Jan 2013 1  
A whiteboard you can instantly share with others and all can start drawing and watching together in real-time

Introduction

This tip will demonstrate the capabilities of HTML5 and ASP.NET SignalR and how to use them in ASP.NET MVC applications. This online whiteboard can be easily shared with anybody via a URL and can start drawing and watching in real-time.

Background

I've been spending some time exploring SignalR recently. For understanding and verifying its capabilities, I planned to try out something with HTML5 and SignalR. Finally, I decided to create an online whiteboard using HTML5 and SignalR for drawing and sharing in real-time.

Using the Code

A live demo is available here. Once a user accesses this link, he will receive a canvas with some drawing tools and URL to share the canvas with others. He can then immediately start drawing and all others will be able to watch the canvas and they can also draw on the canvas.

There are two main areas in the application:

  1. The client-side JavaScript (whiteboard.js). This is the area responsible for drawing on the HTML5 Canvas element as well us creating objects that represent each canvas draw objects to propagate to SignalR hub.
  2. SignalR Hub - This is the area responsible for implementing SignalR for ASP.NET. This receives the messages from a client and propagates to other clients and also maintains a group for set of users to control the proximity of sharing a particular whiteboard.

Whiteboard.js

The core part of this JavaScript is function DrawIt(drawObject, syncServer). This method accepts an object called drawObject which actually contains the co-ordinates for drawing a shape on the canvas and the type of event. This object is generated from different mouse event handling methods in each shape implementation. The below section shows the sample code for generating drawObject while drawing a Line.

function DrawIt(drawObject, syncServer) {
    if (drawObject.Tool == DrawTool.Line) {
        switch (drawObject.currentState) {
            case DrawState.Inprogress:
            case DrawState.Completed:
                context.clearRect(0, 0, canvas.width, canvas.height);
                context.beginPath();
                context.moveTo(drawObject.StartX, drawObject.StartY);
                context.lineTo(drawObject.CurrentX, drawObject.CurrentY);
                context.stroke();
                context.closePath();
                if (drawObject.currentState == DrawState.Completed) {
                    img_update();
                }
                break;
        }
    }   --------}

The drawObject has properties like StartX, StartY, CurrentX, CurrentY, Tool and currentState. The StartX and StartY are the x, y coordinates which are captured on mousedown event on the canvas element. The CurrentX and CurrentY are the coordinates captured on mousemove events. currentState is indicating whether the draw started, inprogress or completed. Tool property is to identify what the currently canvas is trying to draw.

The below code shows the generation of drawObject on Line drawing:

tools.line = function () {
    var tool = this;
    var drawObject = new DrawObject();
    drawObject.Tool = DrawTool.Line;
    this.started = false;
 
    this.mousedown = function (ev) {
        drawObject.currentState = DrawState.Started;
        drawObject.StartX = ev._x;
        drawObject.StartY = ev._y;
        tool.started = true;
    };
 
    this.mousemove = function (ev) {
        if (!tool.started) {
            return;
        }
        drawObject.currentState = DrawState.Inprogress;
        drawObject.CurrentX = ev._x;
        drawObject.CurrentY = ev._y;
        DrawIt(drawObject, true);
    };
 
    this.mouseup = function (ev) {
        if (tool.started) {
            drawObject.currentState = DrawState.Completed;
            drawObject.CurrentX = ev._x;
            drawObject.CurrentY = ev._y;
            DrawIt(drawObject,true);           
            tool.started = false;
        }
    };
};

Signal R Hub

You can install the latest SignarR rc using:

Install-Package Microsoft.AspNet.SignalR -pre 

I used ASP.NET MVC4 for this demo.

The below code will be available in the _Layout.cshtml page:

@Scripts.Render("~/bundles/jquery")
@RenderSection("scripts", required: false) 

In the view, you can include the required script files as shown below:

 @section scripts {
    <script src="~/Scripts/jquery.signalR-1.0.0-rc1.min.js"></script>
    <script src="~/signalR/hubs"></script>
    <script src="../../Scripts/whiteboard.js" type="text/javascript"></script>
    }

The <script src="~/signalR/hubs"></script> indicates that there is SignalR folder which contains the Hub implementation code in the root. This will generate a JavaScript proxy code for handling the connection with SignalR hub.

In the global.asax.cs includes the below code in Application_Start():

RouteTable.Routes.MapHubs();

See the following code used in the SignalR hub i.e. /SignalR/Whiteboardhub.cs file:

namespace OnlineWhiteBoard_4.SignalR
{
    [HubName("whiteboardHub")]
    public class WhiteboardHub:Hub
    {
        public Task Join(string groupName)
        {
            return Groups.Add(Context.ConnectionId, groupName);
        }
       
        public void SendDraw(string drawObject, string sessionId,string groupName)
        {
            Clients.Group(groupName).HandleDraw(drawObject, sessionId);
        }
    }
}

The join method is used to add a user to a particular group and it is called from client-side with a groupname. The client call is as shown below:

whiteboardHub = $.connection.whiteboardHub;
$.connection.hub.start().done(function()
{ whiteboardHub.server.join($("#groupName").val()); }); 

On successful connection to the hub, the client can join a particular group.

The SendDraw is the method which distributes the message from one client to all the other clients. This method has a corresponding implementation in the client-side as shown below:

 whiteboardHub.client.handleDraw = function (message, sessnId) 
{ //code to executed on server call of SendDraw })

Running the Sample

Once you open the source code in Visual Studio, install the SignalR package using below:

Install-Package Microsoft.AspNet.SignalR -pre   

Points of Interest

This application only contains a basic implementation of HTML5 canvas drawing capabilities. We can add more functionality to the client side and still leverage the SignalR communication mechanism used here to propagate the drawings with other clients. Checkout this link to see an excellent implementation of HTML5 canvas. This is just a day's worth of work, so the demo is not tested to perfection. Please let me know if you have any questions or feedback.

References

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here