사이즈 조정

const_yang·2024년 2월 21일
0

하려는 거

마우스 이벤트를 통해 드래그하여 특정 엘레멘트의 사이즈를 조정해 볼 거다.

필요한 거

먼저, 마우스는 아래의 세가지 동작을 한다는 걸 이해하자

  • 마우스를 누른다 (mousedown)
  • 마우스를 움직인다 (mousemove)
  • 마우스에서 손을 뗀다 (mouseup)

작업할 거

  1. 내가 마우스를 눌렀다는 사실을 상태로 기억하고 있자. 그리고 누른 그 지점이 어딘지도 상태로 기억하고 있자.

    우리는 마우스를 누를 때 많은 걸 참조할 수 있다.

암튼, 코드로 작성해 보자.

const [isResizing, setIsResizing] = useState<boolean>(false);

const [initialX, setInitialX] = useState<number>(0);

const handleMouseDown = (e: React.MouseEvent) => {
    setIsResizing(true);
    setInitialX(e.clientX);
};
  1. 이제는 마우스를 움직여 볼건데... 가로 너비의 사이즈를 드래스해서 조정해 볼거다. 필요한게 뭔지 하나씩 생각해보자.
  • 현재 엘레멘트의 너비가 필요하다.
  • 아까 마우스를 누를때 지점의 값이 필요하다(initialX)
  • 마우스를 이동하고서의 지점의 값이 필요하다(1번을 참조해서 e.clientX)
  • 마우스를 이동하고서의 지점 - 마우스 누를 때 지점 = 이동한 거리 (initialX - e.clientX)
  • 현재 너비에서 이동한 거리를 더해준 값이 새로운 너비가 될 거다.

코드로 작성해 보자.

  const handleMouseMove = useCallback(
    (e: MouseEvent) => {
      if (isResizing) {
        const newWidth = width + e.clientX - initialX;
        setInitialX(e.clientX);
        if (newWidth >= 408) {
          setWidth(newWidth);
        }
      }
    },
    [isResizing, initialX, width],
  );
  1. 마지막이다. 마우스에서 손을 뗴보자. 아까 누를 때의 상태의 반대로 상태를 바꾸기만 하면 된다.

코드로 작성해 보자.

  const handleMouseUp = useCallback(() => {
    setIsResizing(false);
  }, []);

전체 코드이고 실제 화면이다.

  const [isResizing, setIsResizing] = useState<boolean>(false);
  const [initialX, setInitialX] = useState<number>(0);
  const [width, setWidth] = useState<number>(408);
  const handleMouseDown = (e: React.MouseEvent) => {
    e.preventDefault();
    setIsResizing(true);
    setInitialX(e.clientX);
  };

  const handleMouseUp = useCallback(() => {
    setIsResizing(false);
  }, []);

  const handleMouseMove = useCallback(
    (e: MouseEvent) => {
      if (isResizing) {
        const newWidth = width + e.clientX - initialX;
        setInitialX(e.clientX);
        if (newWidth >= 408) {
          setWidth(newWidth);
        }
      }
    },
    [isResizing, initialX, width],
  );

  useEffect(() => {
    if (isResizing) {
      document.addEventListener('mousemove', handleMouseMove);
      document.addEventListener('mouseup', handleMouseUp, { once: true });
    } else {
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    }

    return () => {
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    };
  }, [isResizing, handleMouseMove, handleMouseUp]);

0개의 댓글