Project using node.js/Cloning Catch-Mind

Erase canvas with socketIO

Cog Factory 2020. 12. 17. 08:44

Client 'A'가 canvas 를 지우는 logic

// paint.js

let erasing = false;

const handleInputRangeEraser = (e) => {
  if (erasing) {
    const size = e.target.value;
    ctx.lineWidth = size;
  }
};

const erase = () => {
  erasing = true;
  ctx.globalCompositeOperation = "destination-out";
  ctx.lineWidth = eraserRange.value;
};

const handleClickEraser = () => {
  erase();
  getSocket().emit(window.events.erase);
};
// events.js

 erase: "erase",
 erased: "erased",
 setPencil: "setPencil",
 setPenciled: "setPenciled",

erase()함수에서 ctx.globalCompositeOperation은 도형 합성 API다. type을 "destination-out"으로 해놓으면 마우스로 드래그한 부분이 지우개처럼 지워진다. 그리고 pencil과 eraser의 bold range 값은 각각 따로 놔야 한다. ctx.lineWidth로 width 값이 동기화되어 있기 때문에, 지우개 크기를 엄청 키우고 지웠다가 다시 pencil로 전환했을 때 원치 않는 크기로 지워지기 때문이다.

// paint.js

const setPencil = () => {
  erasing = false;
  ctx.globalCompositeOperation = "source-over";
  ctx.lineWidth = boldRange.value;
};

const handleClickColor = (e) => {
  const color = e.target.style.backgroundColor;
  ctx.strokeStyle = color;
  ctx.fillStyle = color;
  setPencil();
  getSocket().emit(window.events.setPencil);
};

const handleClickFill = () => {
  if (filling && !erasing) {
    fill();
    getSocket().emit(window.events.fill, { color: ctx.strokeStyle });
  }
};

  erase 함수를 사용하면 여러 문제점들이 발생한다. erase를 사용하고 난 후, pencil이나 fill mode를 사용할 때 erase의 "destination-out"이 적용될 수 있기 때문이다. 그래서 fill mode를 사용할 때 전체 화면에 "destination-out"이 적용되지 않도록 if 문에 !erasing을 추가했다.

  그리고 pencil 부분은 그림을 그릴 때 색깔이 들어가도록 ctx.globalCompositeOperation="source-over"를 해주고 서버에게 setPencil event를 보낸다.

server

// socketController.js

socket.on(events.erase, () => broadcast(events.erased));
socket.on(events.setPencil, () => broadcast(events.setPenciled));

Client 'A'로 부터 erase와 setPencil event를 수신하면 다른 Client들에게 erased와 setPenciled event를 보낸다.

Other clients

// sockets.js
import {
  handleErased,
  handleSetPenciled,
} from "./paint";

socket.on(events.erased, handleErased);
socket.on(events.setPenciled, handleSetPenciled);
// paint.js

const erase = () => {
  erasing = true;
  ctx.globalCompositeOperation = "destination-out";
  ctx.lineWidth = eraserRange.value;
};

const setPencil = () => {
  erasing = false;
  ctx.globalCompositeOperation = "source-over";
  ctx.lineWidth = boldRange.value;
};

export const handleErased = () => erase();
export const handleSetPenciled = () => setPencil();

server로부터 erased event를 수신하면 canvas에서 마우스로 드래그 한 부분을 지운다.

server로부터 setPenciled event를 수신하면 pencil 설정을 한다.

소스 코드

github.com/zpskek/guessMind-v3/commit/93f28465e85156df9d795ce39caf5b75e5f66b1b