Erase canvas with socketIO
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