bkdragon's log

드래그를 활용한 그리드 아이템 크기 조절 본문

React

드래그를 활용한 그리드 아이템 크기 조절

bkdragon 2024. 6. 29. 16:27

마우스 이벤트를 활용하면 드래그를 통해 html 요소의 크기를 조절할 수 있습니다. 이걸 활용해서 그리드 내부의 요소의 크기를 조정해보겠습니다.

마우스 이벤트 종류

  1. click
    설명: 해당 요소를 클릭했을 때(버튼을 눌렀다가 뗐을 때) 발생합니다.
    사용 예시: 버튼을 클릭하여 폼을 제출하거나 링크를 열 때 사용됩니다.
  2. mousedown
    설명: 해당 요소에서 마우스 버튼을 눌렀을 때 발생합니다.
    사용 예시: 드래그 앤 드롭 기능을 구현할 때, 요소를 선택하는 초기 동작으로 사용됩니다.
  3. mouseup
    설명: 해당 요소에서 눌렀던 마우스 버튼을 뗐을 때 발생합니다.
    사용 예시: 드래그 앤 드롭 기능에서 요소의 위치를 결정하거나, mousedown과 함께 사용하여 클릭 이벤트를 처리할 수 있습니다.
  4. dblclick
    설명: 해당 요소에서 마우스 버튼을 더블 클릭했을 때 발생합니다.
    사용 예시: 파일이나 폴더를 더블 클릭하여 열 때 사용됩니다.
  5. mousemove
    설명: 해당 요소에서 마우스를 움직였을 때 발생합니다.
    사용 예시: 커서 위치를 추적하거나, 캔버스에 그리기 기능을 구현할 때 사용됩니다.
  6. mouseover
    설명: 마우스를 해당 요소 바깥에서 안으로 옮겼을 때 발생합니다.
    사용 예시: 툴팁을 표시하거나, 요소의 스타일을 변경할 때 사용됩니다.
  7. mouseout
    설명: 마우스를 해당 요소 안에서 바깥으로 옮겼을 때 발생합니다.
    사용 예시: 툴팁을 숨기거나, 요소의 스타일을 원래대로 되돌릴 때 사용됩니다.
  8. mouseenter
    설명: 마우스를 해당 요소 바깥에서 안으로 옮겼을 때 발생합니다. 버블링이 발생하지 않습니다.
    사용 예시: 자식 요소가 많은 복잡한 구조에서, 특정 요소에 마우스가 들어왔을 때만 반응하도록 할 때 사용됩니다.
  9. mouseleave
    설명: 마우스를 해당 요소 안에서 바깥으로 옮겼을 때 발생합니다. 버블링이 발생하지 않습니다.
    사용 예시: mouseenter와 함께 사용하여, 특정 요소를 벗어났을 때 동작을 정의할 때 사용됩니다.
  10. contextmenu
    설명: 마우스 오른쪽 버튼을 눌렀을 때 발생합니다.
    사용 예시: 커스텀 컨텍스트 메뉴를 제공하거나, 기본 브라우저 컨텍스트 메뉴를 비활성화할 때 사용됩니다.

과정

  1. mousedown 이벤트로 시작 위치를 얻기:
    • 마우스를 클릭했을 때, mousedown 이벤트를 통해 현재 마우스의 처음 위치를 알아냅니다.
  2. mousemove 이벤트 리스너 등록:
    • 마우스를 클릭했을 때, mousemove 이벤트 리스너를 등록하여 마우스가 움직일 때마다 현재 위치를 추적합니다.
  3. 이동 거리 계산:
    • 처음 위치와 이동된 위치의 차이를 통해 이동한 거리를 계산합니다.
  4. mouseup 이벤트로 이벤트 리스너 제거:
    • mouseup 이벤트가 발생하면 등록된 모든 이벤트 리스너를 제거합니다.

구현

const handleMouseDown = (e, content, index) => {
    const startX = e.clientX;
    const startColSpan = content.values[index].colSpan || 1; 
    const parentElementWidth = document.getElementById('grid-container').clientWidth; // 그리드 컨테이너의 width

    const handleMouseMove = (moveEvent) => {
        const currentX = moveEvent.clientX;
        const diffX = currentX - startX;
        const diffRatio = diffX / parentElementWidth; // 이동 거리 비율
        const newColSpan = Math.max(1, Math.round(startColSpan + diffRatio * content.cols));

        // newColSpan을 이용해 현재 요소의 colSpan 업데이트
        // 상태를 업데이트 해주면 된다.
    };

    const handleMouseUp = () => {
        document.removeEventListener("mousemove", handleMouseMove);
        document.removeEventListener("mouseup", handleMouseUp);
    };

    document.addEventListener("mousemove", handleMouseMove);
    document.addEventListener("mouseup", handleMouseUp);
};

// handleMouseDown은 각 요소에 mousedown 이벤트 리스너로 적용됩니다.

대략적인 html 구조

 <div
    style={{
        display: "grid",
        gap: "16px",
        gridTemplateColumns: `repeat(${content?.cols}, 1fr)`,
    }}
>    
    {content?.values.map((value, index) => (
        <div
            key={index}
            className="flex flex-row items-center w-full"
            style={{
                gridColumn: `span ${
                    value?.colSpan || 1
                }`,
            }}
>    </div>
    ))}
</div>
  • 시작 위치 얻기: mousedown 이벤트가 발생하면 startX에 마우스의 초기 X 좌표를 저장합니다. 또한, 아이템의 초기 colSpan 값을 가져옵니다.
  • mousemove 리스너 등록: 마우스가 움직일 때마다 handleMouseMove 함수가 호출됩니다. 이 함수는 현재 마우스의 X 좌표를 얻고, 초기 좌표와의 차이를 계산하여 이동 비율(diffRatio)을 구합니다. 이를 이용해 새로운 colSpan 값을 계산하고 업데이트합니다.
  • 이벤트 리스너 제거: 마우스를 놓으면(mouseup), 등록된 mousemovemouseup 이벤트 리스너를 제거하여 이벤트 처리를 중지합니다.

결론

위의 예제는 마우스 이벤트를 활용하여 그리드 아이템의 크기(gridColumn)를 조절하는 방법을 설명합니다. 이를 통해 사용자는 드래그 앤 드롭을 통해 그리드 아이템의 크기를 직관적으로 변경할 수 있습니다. 이 방법은 다양한 웹 애플리케이션에서 사용자 경험을 개선하는 데 유용하게 사용될 수 있습니다.

'React' 카테고리의 다른 글

렌더링과 커밋  (2) 2024.09.21
[React Query] 쿼리 키 관리하기  (0) 2024.07.16
Concurrent Rendering  (0) 2023.08.24
Streaming SSR  (0) 2023.08.21
Server Component  (0) 2023.08.21