A really great feature of Sublime Text 2 is the ability to create your own build scripts. A build script is helpful when you are writing in a language that needs to be compiled or executed from terminal / command line. I personally use build scripts to compile the current file into CoffeeScript as well as run the current file in Node JS.
Watch the tutorial or continue reading to learn how to make Sublime Text 2 build scripts. Continue reading →
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.
The first thing we need to do is create a web socket server. For this we will be using Node.js and the module Socket.io. Socket.io makes its super easy to get a web socket server up and running. It even provides a flash fallback for browsers that don’t support native web sockets. In this tutorial we will only be working with browsers that support the canvas element.
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.
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:
Client Side
First, lets quickly get our index.html file up and running. In addition to some bare bones markup, I’m also including jQuery, our Socket.io JS file which is now being served up from our server, a jQuery plugin for drag events, and our own scripts.js file which will hold all the magic.
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.
Create our Canvas Element
# 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.fillStyle = "solid"
App.ctx.strokeStyle = "#bada55"
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 to canvas function
Since drawing to canvas involves beginning, moving and closing paths, i’ve create a short little function that hooks into the jQuery dragstart and drag events.
# 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
Setup our client side web socket
Since we included our file at http://localhost:4000/socket.io/socket.io.js we are able to create an object which we can send our data over. With just a few lines, we create our App.socket object and bind to any incoming web socket events called ‘draw’. We will go over this more soon.
This is where things gets exciting. Now we want to bind a few events to our canvas element. The way this works is when someone draws on the canvas, we immediately use our draw() function to draw to the current canvas as well as send the x and y ordinates over the web socket with socket.io’s emit. In just a bit we will take a look at the server side part of this event and see how the server sends out this data to all open windows.
###
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
Jump back to server side
Now that we know we are sending the x, y and type of event over the web socket, we need to do something with that on our server. What we want to do, is take that data and send it back out to everyone else that has a browser open.
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.
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.
Get Drawing!
One you fully understand how this all works, open your index.html file in any web browser that supports web sockets and canvas (at the time of writing Chrome, Firefox, Safari, Opera and IE9). Check http://caniuse.com/#search=canvas for more support info.
Limitations
As this is a very basic demo, there are a few limitations which can easily be solved with a little more code. Currently the canvas only supports one person drawing at a time, if two or more are drawing, the canvas will be painted sporadically. Also, there is definitely a lot of room to add tools such as brushes, colours, erasers and PNG export. If there is interest, I’ll expand this tutorial series to cover them.
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.
Two things I’ve been working with lately have been Node.js and CoffeeScript. If you haven’t heard of either, Node.js is server side javascript and CoffeeScript is a ruby/python like langage that compiles down to regular javascript.
The way I develop my CoffeeScript is by using the Node.js compiler to watch my `scripts.coffee` for any changes and compile it into normal JavaScript every time I save my file. The process is instant, but I need to watch my terminal window to see if there were any compiling errors. As you can imagine, this can get fairly annoying especially if you aren’t on dual monitors.
So, my solution was to write a Node.js module that would send a growl notification to the user when the compile was finished. I made use of the growlnotify command line plugin for OSX.