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

2 분 소요

til

그림판 색상 변경 버튼

커스텀 페이지에서 그림판 색상 변경 구현을 위한 그림판 펜/지우개 버튼 구현

버튼 레이아웃


// PenEraseButton.tsx
import styled from "styled-components";
import eraser from "../../../assets/images/img_modal/eraser.png";
import pencil from "../../../assets/images/img_modal/pencil.png";

const ButtonStyled =
  styled.div <
  { eraser: boolean } >
  `
  position: relative;
  z-index: 20;
  width: 30px;
  height: 30px;
  margin-left: 20px;
  border: none;
  cursor: grab;

  background-image: url(${(props) => (props.eraser ? eraser : pencil)});
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;

  &::before {
    content: '';
    position: absolute;
    top: -6px;
    left: -6px;
    right: -6px;
    bottom: -6px;
    border-radius: 50%;
    background-color: rgba(0, 0, 0, 0.1);
    transform: scale(0);
    transition: transform 0.2s ease-in-out;
  }

  &:hover::before {
    transform: scale(1);
  }

  &:active {
    filter: brightness(1.2);
  }
`;

interface EraseButtonProps {
  onClick: () => void;
  eraser: boolean;
}

function EraseButton({ eraser, onClick }: EraseButtonProps) {
  const handleButtonClick = () => {
    onClick();
  };

  return (
    <ButtonStyled eraser={eraser} onClick={handleButtonClick}></ButtonStyled>
  );
}

export default EraseButton;

그림판에서 펜과 지우개 기능은 하나의 버튼으로 만들어 그리기모드/지우개모드로 변경되는 방식으로 구현하였다.

레이아웃은 다음과 같이 구현하였다.
펜(그리기모드) 버튼

til

지우개(지우개모드) 버튼
til

버튼 모드


interface EraseButtonProps {
  onClick: () => void;
  eraser: boolean;
}

인터페이스 정의

function EraseButton({ eraser, onClick }: EraseButtonProps) {
  const handleButtonClick = () => {
    onClick();
  };

  return (
    <ButtonStyled eraser={eraser} onClick={handleButtonClick}></ButtonStyled>
  );
}

eraseronClick 프롭스를 받는다. 버튼이 어떤 모드(지우기 또는 그리기)로 설정되어 있는지와 클릭 이벤트 핸들러를 받는다.


캔버스에 적용

handleMouseMove 함수

마우스가 캔버스 위에서 움직일 때 호출되는 함수
그림을 그리는 동작과 이 후에 이미지 드래그를 처리할때 사용

const handleMouseMove = (
  event: React.MouseEvent<HTMLCanvasElement, MouseEvent>
) => {
  // 현재 마우스 커서의 좌표를 계산
  const canvas = canvasRef.current;
  if (!canvas) return;

  const ctx = canvas.getContext("2d");
  if (!ctx) return;

  const rect = canvas.getBoundingClientRect();
  const x = event.clientX - rect.left;
  const y = event.clientY - rect.top;

  // 이미지 드래그 중인 경우
  if (isDragging && draggedImageIndex >= 0) {
    const draggedImage = images[draggedImageIndex];

    // 드래그 중인 이미지의 위치를 마우스 커서 위치로 업데이트
    const newImages = images.map((imageData, index) => {
      if (index === draggedImageIndex) {
        return {
          ...imageData,
          x: x - draggedImage.width / 2,
          y: y - draggedImage.height / 2,
        };
      }
      return imageData;
    });

    setImages(newImages);
    updateImages(newImages); // 이미지 상태를 업데이트
  } else {
    // 그리기 모드일 때
    if (event.buttons !== 1) return;

    // 그리기 관련 설정을 설정
    ctx.globalCompositeOperation = eraser ? "destination-out" : "source-over";
    ctx.lineWidth = size;
    ctx.strokeStyle = eraser ? "rgba(0,0,0,1)" : color;

    // 선을 그림
    ctx.lineTo(x, y);
    ctx.stroke();
  }
};
  • 그리기 모드일 때, ctx.globalCompositeOperation을 설정하여 지우개 모드인지 그리기 모드인지 결정한다.
  • ctx.lineWidthctx.strokeStyle를 설정하여 선의 두께와 색상을 지정한다.
  • ctx.lineTo(x, y)ctx.stroke()를 사용하여 선을 그린다.

handleEraseButtonClick 함수

const handleEraseButtonClick = () => {
  setEraser(!eraser); // 지우개 모드 전환
  setDrawingMode(false); // 그리기 모드 비활성화
  setIsDragging(false); // 이미지 드래그 비활성화
};
  • setEraser(!eraser)를 사용하여 현재 지우개 모드의 상태를 토글
  • setDrawingMode(false)를 사용하여 그리기 모드를 비활성화
  • setIsDragging(false)를 사용하여 이미지 드래그를 비활성화

정리


이 두 함수는 사용자의 상호작용에 따라 그림 그리기와 이미지 드래그, 지우개 모드 전환을 관리한다. 이를 통해 사용자가 캔버스를 자유롭게 조작하고 그림을 그리며 편집할 수 있게 된다.

댓글남기기