diff --git a/examples/whiteboard/README.md b/examples/whiteboard/README.md new file mode 100644 index 0000000000..8d443db8a1 --- /dev/null +++ b/examples/whiteboard/README.md @@ -0,0 +1,17 @@ + +# Socket.IO Collaborative Whiteboard + +A simple collaborative whiteboard for socket.io + +## How to use + +``` +$ npm i && npm start +``` + +And point your browser to `http://localhost:3000`. Optionally, specify +a port by supplying the `PORT` env variable. + +## Features + +- draw on the whiteboard and all other users will see you drawings live diff --git a/examples/whiteboard/index.js b/examples/whiteboard/index.js new file mode 100644 index 0000000000..44cc97f9d3 --- /dev/null +++ b/examples/whiteboard/index.js @@ -0,0 +1,16 @@ + +const express = require('express'); +const app = express(); +const http = require('http').Server(app); +const io = require('socket.io')(http); +const port = process.env.PORT || 3000; + +app.use(express.static(__dirname + '/public')); + +function onConnection(socket){ + socket.on('drawing', (data) => socket.broadcast.emit('drawing', data)); +} + +io.on('connection', onConnection); + +http.listen(port, () => console.log('listening on port ' + port)); diff --git a/examples/whiteboard/package.json b/examples/whiteboard/package.json new file mode 100644 index 0000000000..cb78467785 --- /dev/null +++ b/examples/whiteboard/package.json @@ -0,0 +1,19 @@ +{ + "name": "whiteboard", + "version": "1.0.0", + "description": "A simple collaborative whiteboard using socket.io", + "main": "index.js", + "keywords": [ + "socket.io", + "whiteboard" + ], + "dependencies": { + "express": "4.9.x", + "socket.io": "latest" + }, + "scripts": { + "start": "node index" + }, + "author": "Damien Arrachequesne", + "license": "MIT" +} diff --git a/examples/whiteboard/public/index.html b/examples/whiteboard/public/index.html new file mode 100644 index 0000000000..710932a897 --- /dev/null +++ b/examples/whiteboard/public/index.html @@ -0,0 +1,23 @@ + + + + + Socket.IO whiteboard + + + + + + +
+
+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/examples/whiteboard/public/main.js b/examples/whiteboard/public/main.js new file mode 100644 index 0000000000..808f52b223 --- /dev/null +++ b/examples/whiteboard/public/main.js @@ -0,0 +1,100 @@ +'use strict'; + +(function() { + + var socket = io(); + var canvas = document.getElementsByClassName('whiteboard')[0]; + var colors = document.getElementsByClassName('color'); + var context = canvas.getContext('2d'); + + var current = { + color: 'black' + }; + var drawing = false; + + canvas.addEventListener('mousedown', onMouseDown, false); + canvas.addEventListener('mouseup', onMouseUp, false); + canvas.addEventListener('mouseout', onMouseUp, false); + canvas.addEventListener('mousemove', throttle(onMouseMove, 10), false); + + for (var i = 0; i < colors.length; i++){ + colors[i].addEventListener('click', onColorUpdate, false); + } + + socket.on('drawing', onDrawingEvent); + + window.addEventListener('resize', onResize, false); + onResize(); + + + function drawLine(x0, y0, x1, y1, color, emit){ + context.beginPath(); + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.strokeStyle = color; + context.lineWidth = 2; + context.stroke(); + context.closePath(); + + if (!emit) { return; } + var w = canvas.width; + var h = canvas.height; + + socket.emit('drawing', { + x0: x0 / w, + y0: y0 / h, + x1: x1 / w, + y1: y1 / h, + color: color + }); + } + + function onMouseDown(e){ + drawing = true; + current.x = e.clientX; + current.y = e.clientY; + } + + function onMouseUp(e){ + if (!drawing) { return; } + drawing = false; + drawLine(current.x, current.y, e.clientX, e.clientY, current.color, true); + } + + function onMouseMove(e){ + if (!drawing) { return; } + drawLine(current.x, current.y, e.clientX, e.clientY, current.color, true); + current.x = e.clientX; + current.y = e.clientY; + } + + function onColorUpdate(e){ + current.color = e.target.className.split(' ')[1]; + } + + // limit the number of events per second + function throttle(callback, delay) { + var previousCall = new Date().getTime(); + return function() { + var time = new Date().getTime(); + + if ((time - previousCall) >= delay) { + previousCall = time; + callback.apply(null, arguments); + } + }; + } + + function onDrawingEvent(data){ + var w = canvas.width; + var h = canvas.height; + drawLine(data.x0 * w, data.y0 * h, data.x1 * w, data.y1 * h, data.color); + } + + // make the canvas fill its parent + function onResize() { + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + } + +})(); diff --git a/examples/whiteboard/public/style.css b/examples/whiteboard/public/style.css new file mode 100644 index 0000000000..437a29cfef --- /dev/null +++ b/examples/whiteboard/public/style.css @@ -0,0 +1,44 @@ + +/** + * Fix user-agent + */ + +* { + box-sizing: border-box; +} + +html, body { + height: 100%; + margin: 0; + padding: 0; +} + +/** + * Canvas + */ + +.whiteboard { + height: 100%; + width: 100%; + position: absolute; + left: 0; + right: 0; + bottom: 0; + top: 0; +} + +.colors { + position: fixed; +} + +.color { + display: inline-block; + height: 48px; + width: 48px; +} + +.color.black { background-color: black; } +.color.red { background-color: red; } +.color.green { background-color: green; } +.color.blue { background-color: blue; } +.color.yellow { background-color: yellow; }