class CanvasReceiverController { private canvasDiv: HTMLDivElement; private canvas!: HTMLCanvasElement; private ctx!: CanvasRenderingContext2D | null; private ws: WebSocket; /** * Represents whether the app is waiting for the first coordinates of a draw path. The first * coordinates need to be handled with the moveTo canvas method instead of lineTo, therefore * this variable is needed to decide how to handle the next coordinates. */ private waiting: boolean = false; constructor() { this.canvasDiv = document.querySelector('#canvas') as HTMLDivElement; this.createCanvas(); this.ws = new WebSocket('ws://localhost:8081', 'json'); this.ws.onmessage = message => this.processMessage(message); this.ws.onopen = () => this.ws.send('RECEIVER'); } private createCanvas() { this.canvas = document.createElement('canvas'); this.canvasDiv.appendChild(this.canvas); this.canvas.width = this.canvas.offsetWidth; this.canvas.height = this.canvas.offsetHeight; if (!this.canvas.getContext) { alert('Canvas API unavailable, drawing will not work!'); } else { this.ctx = this.canvas.getContext('2d'); } } processMessage(message: MessageEvent) { switch (message.data) { case 'CLEAR': this.clear(); break; case 'START': this.startDrawing(); break; case 'STOP': this.stopDrawing(); break; default: this.draw(JSON.parse(message.data)); break; } } startDrawing() { console.log('Received START command'); if (!this.ctx) { return; } this.ctx.beginPath(); this.waiting = true; } stopDrawing() { if (!this.ctx) { return; } } private clear() { this.canvasDiv.removeChild(this.canvas); this.createCanvas(); } draw(coordinates: Coordinates) { if (!this.ctx) { return; } if (this.waiting) { this.waiting = false; this.ctx.moveTo(coordinates.x, coordinates.y); } else { this.ctx.lineTo(coordinates.x, coordinates.y); } this.ctx.lineWidth = 1; this.ctx.stroke(); } } class Coordinates { public x: number; public y: number; constructor(x: number, y: number) { this.x = x; this.y = y; } } const app = new CanvasReceiverController(); export { app };