socket.io 白板

建立一個專案目錄 week15

在這裡開啟終端機,並且開啟 vscode

code .	

新增一個檔案 package.json 並且貼上以下程式碼

{
"name": "whiteboard",
"version": "1.0.0",
"description": "A simple collaborative whiteboard using socket.io",
"main": "index.js",
"keywords": [
"socket.io",
"whiteboard"
],
"dependencies": {
"express": "~4.17.1",
"socket.io": "~2.3.0"
},
"scripts": {
"start": "node index"
},
"author": "Damien Arrachequesne",
"license": "MIT"
}

安裝基本 npm 套件

npm install

建立一個資料夾 public

在 public 資料夾新增檔案 index.html 以及 style.css 並且覆蓋以下程式碼

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Socket.IO whiteboard</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas class="whiteboard"></canvas>
<div class="colors">
<div class="color black"></div>
<div class="color red"></div>
<div class="color green"></div>
<div class="color blue"></div>
<div class="color yellow"></div>
<div class="drawtext">Text</div>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="/main.js"></script>
</body>
</html>
/**
* 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;
border: 1px solid orange;
border-radius: 20px;
padding: 10px;
background-color:lightblue;
margin:10px;
}
.color {
height: 48px;
width: 48px;
border-radius: 50%;
margin-top: 10px;
border: 2px solid yellow;
}
.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; }
.drawtext {
height: 48px;
width: 48px;
margin-top: 10px;
border: 2px solid yellow;
border-radius: 50%;
text-align: center;
font-weight: 900;
}

在根目錄建立一個檔案 index.js 並且覆蓋以下程式碼

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));
socket.on('texting', (data) => socket.broadcast.emit('texting', data));
}
io.on('connection', onConnection);
http.listen(port, () => console.log('listening on port ' + port));

執行白板測試

node index.js

進入網址 http://localhost:3000/ 就可以看到白板了

在 public 資料夾裡面新增一個檔案 main.js 並且貼上以下程式碼

'use strict';
(function () {
var socket = io();
var canvas = document.getElementsByClassName('whiteboard')[0];
var colors = document.getElementsByClassName('color');
var drawtext = document.getElementsByClassName('drawtext')[0];
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);
//Touch support for mobile devices
canvas.addEventListener('touchstart', onMouseDown, false);
canvas.addEventListener('touchend', onMouseUp, false);
canvas.addEventListener('touchcancel', onMouseUp, false);
canvas.addEventListener('touchmove', throttle(onMouseMove, 10), false);
for (var i = 0; i < colors.length; i++) {
colors[i].addEventListener('click', onColorUpdate, false);
}
drawtext.addEventListener('click', onTextUpdate, false);
function onTextUpdate(e) {
socket.emit('texting', {
text: "Hello World"
});
}
socket.on('drawing', onDrawingEvent);
socket.on('texting', onDrawingTextEvent);
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 || e.touches[0].clientX;
current.y = e.clientY || e.touches[0].clientY;
}
function onMouseUp(e) {
if (!drawing) { return; }
drawing = false;
drawLine(current.x, current.y, e.clientX || e.touches[0].clientX, e.clientY || e.touches[0].clientY, current.color, true);
}
function onMouseMove(e) {
if (!drawing) { return; }
drawLine(current.x, current.y, e.clientX || e.touches[0].clientX, e.clientY || e.touches[0].clientY, current.color, true);
current.x = e.clientX || e.touches[0].clientX;
current.y = e.clientY || e.touches[0].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);
}
function onDrawingTextEvent(data) {
console.log("drawing text");
context.font = "30px Arial";
context.fillText(data.text, 100, 100);
}
// make the canvas fill its parent
function onResize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
})();

同時開啟兩個頁面,上面的畫面可以同步

SHXJ
Latest posts by SHXJ (see all)

發佈留言