[React] 커스텀 그림판 Resize
그림판 창크기 오류
커스텀 페이지에서 그림판의 창크기를 변경할 시 그림이 삭제되는 오류 수정
문제된 부분(화면 기록을 까먹었다..ㅜ)
이렇게 열씸히 그려놓고 창 크기를 조절하려고하면 그림이 다 날아가버림 ㅠㅜ
그림판에 그림을 그린 뒤 창 크기를 줄이거나 늘리게 되면 캔버스 자체의 크기가 변경되기 때문에 이전에 그렸던 그림들이 삭제되는 오류가 있었다.
문제 접근
- 이전 그림을 저장해서 창 크기를 조절했을때 다시 불러오는 방식
- 창 크기를 제한하여 고정크기로 만드는 방식
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.offsetWidth
와canvas.offsetHeight
를 사용하여 캔버스의 부모 요소인CanvasWrapper
의 크기를 가져온다. - 새로 조정된 캔버스에 이전 캔버스의 내용을
복사하여 그린다.
이를 통해 캔버스의 크기가 조정되더라도 이전에 그려진 그림이 보존된다.
결과
❖ 추후 개선사항: 원하는대로 이전 그림이 보존은 되지만 창 크기를 조절하면 이전 그림의 화질이 저하되는 문제가 존재한다.
댓글남기기