📌 작성자 개발 환경
OS: Mac OS
Tool: Visual Studio Code

2 분 소요

til

그림판 창크기 오류

커스텀 페이지에서 그림판의 창크기를 변경할 시 그림이 삭제되는 오류 수정

문제된 부분(화면 기록을 까먹었다..ㅜ)


이렇게 열씸히 그려놓고 창 크기를 조절하려고하면 그림이 다 날아가버림 ㅠㅜ

til

그림판에 그림을 그린 뒤 창 크기를 줄이거나 늘리게 되면 캔버스 자체의 크기가 변경되기 때문에 이전에 그렸던 그림들이 삭제되는 오류가 있었다.
문제 접근

  1. 이전 그림을 저장해서 창 크기를 조절했을때 다시 불러오는 방식
  2. 창 크기를 제한하여 고정크기로 만드는 방식

UX를 고려했을때 1번의 방식으로 이 문제를 해결하는 방식으로 해결했다.

수정한 코드

useEffect(() => {
  const handleResize = () => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const tempCanvas = document.createElement("canvas");
    const tempCtx = tempCanvas.getContext("2d");
    if (!tempCtx) return;

    // 임시 캔버스에 현재 캔버스의 내용을 복사
    tempCanvas.width = canvas.width;
    tempCanvas.height = canvas.height;
    tempCtx.drawImage(canvas, 0, 0, canvas.width, canvas.height);

    // 캔버스 크기를 브라우저 창 크기에 맞게 조정
    canvas.width = canvas.offsetWidth;
    canvas.height = canvas.offsetHeight;

    // 새 캔버스에 이전 캔버스 내용 복사
    const ctx = canvas.getContext("2d");
    if (!ctx) return;

    ctx.lineCap = "round";
    ctx.lineJoin = "round";
    ctx.lineWidth = size;
    ctx.strokeStyle = color;
    ctx.globalCompositeOperation = eraser ? "destination-out" : "source-over";

    ctx.drawImage(tempCanvas, 0, 0, canvas.width, canvas.height);
  };

  // 창 크기가 변경될 때마다 handleResize 함수 호출
  window.addEventListener("resize", handleResize);

  // 컴포넌트가 unmount될 때 이벤트 리스너 제거
  return () => {
    window.removeEventListener("resize", handleResize);
  };
}, [size, color, eraser]);

handleResize 함수


자세한 주석을 더한 리뷰

const handleResize = () => {
  const canvas = canvasRef.current; // 현재 캔버스 요소 가져옴
  if (!canvas) return;

  const tempCanvas = document.createElement("canvas"); // 임시 캔버스 생성
  const tempCtx = tempCanvas.getContext("2d"); // 임시 캔버스의 2D 컨텍스트 가져옴
  if (!tempCtx) return;

  // 현재 캔버스의 내용을 임시 캔버스에 복사
  tempCanvas.width = canvas.width;
  tempCanvas.height = canvas.height;
  tempCtx.drawImage(canvas, 0, 0, canvas.width, canvas.height);

  // 캔버스의 크기를 브라우저 창 크기에 맞게 조정
  canvas.width = canvas.offsetWidth;
  canvas.height = canvas.offsetHeight;

  const ctx = canvas.getContext("2d"); // 캔버스의 2D 컨텍스트 가져옴
  if (!ctx) return;

  // 선의 스타일과 속성 설정
  ctx.lineCap = "round"; // 라인의 끝 모양을 둥글게 설정
  ctx.lineJoin = "round"; // 라인의 교차점을 둥글게 설정
  ctx.lineWidth = size; // 라인의 두께 설정
  ctx.strokeStyle = color; // 라인의 색상 설정
  ctx.globalCompositeOperation = eraser ? "destination-out" : "source-over"; // 블렌딩 모드 설정

  // 임시 캔버스의 내용을 새 캔버스에 그림
  ctx.drawImage(tempCanvas, 0, 0, canvas.width, canvas.height);
};

// 창 크기 변경 시 handleResize 함수 호출
window.addEventListener("resize", handleResize);

// 컴포넌트가 unmount될 때 이벤트 리스너 제거
return () => {
  window.removeEventListener("resize", handleResize);
};
  • 임시 캔버스(tempCanvas)를 생성하고, getContext('2d') 메서드를 사용하여 2D 컨텍스트(tempCtx)를 가져온다.
  • 임시 캔버스에 현재 캔버스의 내용을 복사, 이를 통해 캔버스의 현재 상태를 임시 캔버스에 보존한다.
  • 캔버스의 크기를 브라우저 창 크기에 맞게 조정합니다. canvas.offsetWidthcanvas.offsetHeight를 사용하여 캔버스의 부모 요소인 CanvasWrapper의 크기를 가져온다.
  • 새로 조정된 캔버스에 이전 캔버스의 내용을 복사하여 그린다. 이를 통해 캔버스의 크기가 조정되더라도 이전에 그려진 그림이 보존된다.

결과

til

❖ 추후 개선사항: 원하는대로 이전 그림이 보존은 되지만 창 크기를 조절하면 이전 그림의 화질이 저하되는 문제가 존재한다.

댓글남기기