Today, we will create a collaborative drawing application with node.js and socket.io.
Open your terminal,
Create a "draw09" directory
Go in your "draw09" folder
Initialize npm
Install express
Install socket.io
Our server will have two tasks :
In order to exchange data from the server to the client and vice versa, we need the "clienttoserver" and "servertoclient" communication pipes.
To simplify the code, we will define "c2s" as "clienttoserver" and "s2c" as the "servertoclient" communication channels (pipes).
Here is the code of the server (on port 1234):
const app = require('express')()
const http = require('http').Server(app)
const io = require('socket.io')(http)
var port=1234
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index_dessin.html')
})
io.on('connection', (socket) => {
console.log('A new user is connected...')
socket.on('disconnect', () => {
console.log('User disconnected...')
});
socket.on('c2s', (data) => {
console.log('client->server // data (x,y): ('+data.x+', '+data.y+')')
io.emit('s2c', data)
})
})
http.listen(port, () => {
console.log('listening on port '+port+'...')
})
The client has two tasks: sending new drawn points to the server and processing responses (many other client points) from the server.
It is a "simple" HTML and JS page using JQuery.
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: sans-serif;
}
#drawing {
margin: 1vw;
padding: 1vw;
width: 600px;
height: 400px;
border: 1px solid #0001ff;
border-radius: 16px;
}
</style>
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
</head>
<body>
<h1>Collaborative Drawing</h1>
<div id="drawing"></div>
<script src="/socket.io/socket.io.js"></script>
<script>
$(document).ready(function () {
var socket = io()
// source: https://ourcodeworld.com/articles/read/49/draw-points-on-a-canvas-with-javascript-html5
$("#drawing").click(function(e){
var x=e.clientX
var y=e.clientY
socket.emit('???', {x: x, y: y});
console.log("New point sent...")
});
socket.on('???', function(data) {
console.log("New point received...")
$('<svg height="3px" width="3px"><circle cx="1" cy="1" r="1" fill="red" /></svg>')
.css({position:"absolute",left:data.x,top:data.y})
.appendTo($('#drawing'))
})
})
</script>
</body>
</html>
(##) Copy the previous code and change the ??? to exchange data between the client and the server using the correct communication pipes.
Test you collaborative drawing, it will normally work!
Now, we want to do continuous drawing instead of one point at a time.
Modify your code to realize continuous drawing by inserting (on the client) the following code (from the source: https://stackoverflow.com/questions/4961072/jquery-continuous-mousedown):
var mouseisdown = false
$("#drawing").mousedown(function(event) {
mouseisdown = true
doSomething(event)
}).mouseup(function(event) {
mouseisdown = false
})
$("#drawing").mousemove(function(event) {
if (mouseisdown) {
doSomething(event)
}
})
function doSomething(e){
//Code goes here
var x=e.clientX
var y=e.clientY
???
console.log("New point sent...")
}
Add the previous code to your client and replace the ??? by the thing you want to emit to the server...
You should obtain continuous drawing for your collaborative application.
Color: <select name="color" id="color">
<option value="red">red</option>
<option value="green">green</option>
<option value="blue">blue</option>
</select><br />
We want to draw the actual drawing when a new client will connect to the application.
We need to modify the server in order to save the drawn points in an array of points.
When a new client connects to our application, the server will have to send it the full list of drawn points.
Add the following code (at the good location) to draw the entire list of points to any new connected client.
var listOfPoints=[]
listOfPoints.forEach(function(point) {
socket.emit('s2c', point)
})
Now, every new connected client will have the full points on the screen (instead of a blank screen).
In the next figure, client 1 draw in red, client 2 draw in green and when client 3 connected to the application, all the previous points were automatically drawn on the third screen !