Web sockets and Canvas are two really cool features that are currently being implemented into browsers. This tutorial will give you a short rundown of how they both work as well as create a realtime drawing canvas that is powered by Node.js and web sockets. For simplicity's sake, I'll be writing all the code in coffeescript. If you prefer regular 'ol JavaScript, take a look at the corresponding .js files. I've also left out the CSS for the same reason.
* <a href="https://github.com/wesbos/websocket-canvas-draw" target="_blank">Download the code on GitHub</a>
* <a href="http://twitter.com/wesbos">Follow @wesbos on Twitter</a>
If you don't have Socket.io installed yet, make sure you do so by typing npm install socket.io
into your terminal.
For now, lets just set up the web socket server. Create your server.coffee
file with the following configuration.
io = require('socket.io').listen(4000)
io.sockets.on 'connection', (socket) ->
Compile your coffeescript and hop back into your terminal and type node server.js
. You now have a web socket server running on port 4000.
If you go to localhost:4000 you'll see the following:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.event.drag-2.0.js"></script>
<script src="http://localhost:4000/socket.io/socket.io.js"></script>
<script type="text/javascript" src="scripts.js"></script>
<link rel="stylesheet" href="style.css" />
<title>HTML5 Canvas + Node.JS Socket.io</title>
</head>
<body>
<article><!-- our canvas will be inserted here--></article>
<!-- Scripts required -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.event.drag-2.0.js"></script>
<script src="http://localhost:4000/socket.io/socket.io.js"></script>
<script type="text/javascript" src="scripts.js"></script>
</body>
Now that we have our server up and running, we can write some code which will draw to the canvas. Create a new file called scripts.coffee
. All of the following code happens within the App.init() method which we will trigger on the jQuery document ready.
# setup our application with its own namespace
App = {}
###
Init
###
App.init = ->
App.canvas = document.createElement 'canvas' #create the canvas element
App.canvas.height = 400
App.canvas.width = 800 #size it up
document.getElementsByTagName('article')[0].appendChild(App.canvas) #append it into the DOM
App.ctx = App.canvas.getContext("2d") # Store the context
# set some preferences for our line drawing.
App.ctx.fill
App.ctx.stroke
App.ctx.lineWidth = 5
App.ctx.lineCap = "round"
# Draw Function
App.draw = (x,y,type) ->
if type is "dragstart"
App.ctx.beginPath()
App.ctx.moveTo(x,y)
else if type is "drag"
App.ctx.lineTo(x,y)
App.ctx.stroke()
else
App.ctx.closePath()
return
# Draw Function
App.draw = (x,y,type) ->
if type is "dragstart"
App.ctx.beginPath()
App.ctx.moveTo(x,y)
else if type is "drag"
App.ctx.lineTo(x,y)
App.ctx.stroke()
else
App.ctx.closePath()
return
# Sockets!
App.socket = io.connect('http://localhost:4000')
App.socket.on 'draw', (data) ->
App.draw(data.x,data.y,data.type)
###
Draw Events
###
$('canvas').live 'drag dragstart dragend', (e) ->
type = e.handleObj.type
offset = $(this).offset()
e.offsetX = e.layerX - offset.left
e.offsetY = e.layerY - offset.top
x = e.offsetX
y = e.offsetY
App.draw(x,y,type)
App.socket.emit('drawClick', { x : x, y : y, type : type})
return
Our updated server.coffee file now looks like this. We first wait for a connection event, then wait for a 'drawClick' event to be sent by a browser. When that happens we take the data and send it out to everyone else with a browser open. THe server side script we wrote earlier will then paint the canvas.
io = require('socket.io').listen(4000)
io.sockets.on 'connection', (socket) ->
socket.on 'drawClick', (data) ->
socket.broadcast.emit 'draw',{ x : data.x, y : data.y, type: data.type}
return
return
You'll now need to restart your web socket server as we have made changes to it. Hit control-c to kill it, and node type node server.js
to restart it.
If you're interested in getting this up and running in the real world and off of your localhost, I was able to get mine running on Amazons free micro instance of EC2 although this involves installing Node and NPM all over again. Also note you should run your server on port 80 rather than 4000.
Please feel free to download, hack, complain, fork or contribute to the project on my github account.
Find an issue with this post? Think you could clarify, update or add something?
All my posts are available to edit on Github. Any fix, little or small, is appreciated!