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:
- 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.
- 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