В этом разделе мы увидим, как нарисовать фигуру на одной вкладке и отобразить ее на других. Мы также видим, как очистить рисунок на всех открытых вкладках.
Проверка применимости сообщения
Вспомните, когда сервер получает событие отрисовки, он просто транслирует его всем клиентам. Таким образом, клиент должен убедиться, что 1) сообщение относится к комнате, в которой оно находится, и 2) оно не было отправлено этим клиентом. Для этого мы рефакторим Socket.handleMessage для декодирования полученного JSON и выполняем следующие проверки:
async handleMessage(msg) {
const msgDecoded = JSON.parse(await msg.data.text());
if (msgDecoded.roomName === this.room.room && msgDecoded.roomId !== this.room.id) {
this.canvas.drawMessage(msgDecoded);
}
}
Этот код предполагает, что нам нужны ссылки на объекты Room и Canvas. Поскольку объект Room определен перед Socket в index.html, его можно просто передать конструктору в качестве параметра.
const socket = new Socket(room);
Однако объект Canvas определяется после. Вы можете добавить холст как свойство напрямую:
socket.canvas = canvas;
Или вы можете использовать метод установки, если хотите быть более формальным:
setCanvas(canvas) {
this.canvas = canvas;
}
Мы будем использовать последний для этого проекта. Теперь мы определяем метод, который на самом деле рисует то, что говорится в сообщении:
drawMessage(msg) {
const {mode, color, startPoint, endPoint} = msg;
this.ctx.strokeStyle = color;
this.ctx.fillStyle = color;
if (mode === 'Line') {
this.drawLine(startPoint, endPoint);
} else if (mode === 'Hollow Rectangle') {
this.drawHollowRectangle(startPoint, endPoint);
} else if (mode === 'Filled Rectangle') {
this.drawFilledRectangle(startPoint, endPoint);
} else if (mode === 'Hollow Circle') {
this.drawHollowCircle(startPoint, endPoint);
} else if (mode === 'Filled Circle') {
this.drawFilledCircle(startPoint, endPoint);
}
this.ctx.strokeStyle = this.activeColor;
this.ctx.fillStyle = this.activeColor;
}
Обратите внимание, как этот метод написан, чтобы не мешать начальной/конечной точкам и цвету, которые есть у этого пользователя. Он должен изменить стили обводки и заливки текущего холста клиента, чтобы использовать правильный цвет, отправленный с сервера. Но как только он закончил рисовать, он восстанавливает цвет до того, каким он был изначально.
После обновления вкладок вы должны увидеть фигуру, нарисованную на одной вкладке, которая появится на другой!
Очистка на всех вкладках
Чтобы очистить рисунок на всех вкладках, мы добавляем метод для сокетов для отправки сообщения очистки, модифицируем drawMessage для получения сообщения и обновляем кнопку «Очистить», чтобы фактически отправлять сообщение сокета. К счастью, это все довольно небольшие изменения.
Метод отправки ясного сообщения в классе Socket:
sendClear() {
this.socket.send(JSON.stringify({
type: 'clear',
roomId: this.room.id,
roomName: this.room.room
});
}
Затем мы обновляем handleMessage, чтобы сообщать об очистке, и отправляем его правильному методу на Canvas:
async handleMessage(msg) {
const msgDecoded = JSON.parse(await msg.data.text());
if (msgDecoded.roomName == this.room.room && msgDecoded.roomId !== this.room.id) {
if (msgDecoded.type === 'draw') {
this.canvas.drawMessage(msgDecoded);
} else if (msgDecoded.type === 'clear') {
this.canvas.clearMessage(msgDecoded);
}
}
}
В Canvas нам нужно обновить существующий метод, который очищает холст для отправки сообщения сокета, и добавить метод, который фактически выполняет очистку при получении сообщения сокета:
clear() {
this.ctx.clearRect(0, 0, 500, 500);
this.socket.sendClear();
}
clearMessage(msg) {
this.ctx.clearRect(0, 0, 500, 500);
}
Собираем вместе
Обновите вкладки и начните рисовать фигуры. Затем нажмите «Очистить» на одной из вкладок и наблюдайте, как фигуры исчезают на обеих! Совместный аспект проекта в настоящее время в основном завершен, но есть одна большая недостающая функция. Как только мы закрываем вкладки, изображение теряется. Было бы неплохо, если бы мы могли сохранить изображение в базе данных и просмотреть его позже? В следующем разделе мы начнем с этого.
Вот как должен выглядеть код в конце этого раздела.