[React]react-rnd로 이미지 크기 조절 및 드래그

이미지의 크기를 조절하고 드래그하는 기능을 구현하기 위해서 react-rnd 라이브러리를 사용했다.

https://www.npmjs.com/package/react-rnd

 

react-rnd

A draggable and resizable React Component. Latest version: 10.4.10, last published: 23 days ago. Start using react-rnd in your project by running `npm i react-rnd`. There are 416 other projects in the npm registry using react-rnd.

www.npmjs.com

 

구현해야 했던 기능으로는

1. 이미지 드래그 (+ 드래그 바운더리 지정)

2. 이미지 크기 조절 (+ 최소 크기 지정)

이 두 가지 여서 react-rnd를 사용하게 되었다.

구글링을 했는데 생각보다 자료가 많이 없어서 당황했지만.. 위의 문서를 보고 구현할 수 있었다.

 

 

⭐️ 설치

npm i -S react-rnd

 

⭐️ 사용방법

<Rnd
    default={{
      x: initialPo.x,
      y: initialPo.y,
      width: 100,
      height: 100,
    }}
    minWidth={50}
    minHeight={50}
    bounds="#limit"
    resizeHandleStyles={handleStyles}
    lockAspectRatio={true}
  >
    <img
      src={image}
    />
</Rnd>
  • default: 초기 위치(x, y)와 초기 크기(width, height)를 설정한다.
  • minWidth, minHeight: 최소 크기를 설정한다.
  • bounds: 이미지 이동 경로를 제한한다. id=limit인 div를 가져와서 제한해주었다.
  • lockAspectRatio: true로 설정해주면 이미지 크기 조절 시, 초기 이미지의 비율을 유지한다.
  • resizeHandleStyles: 이미지 크기 조절을 편하게 하기 위한 가이드를 스타일링한다.
 const handleStyles =
    selected == index
      ? {
          bottomLeft: {
            width: "10px",
            height: "10px",
            border: "0.5px solid #777777",
            left: "0px",
            bottom: "0px",
          },
          bottomRight: {
            width: "10px",
            height: "10px",
            border: "0.5px solid #777777",
            right: "0px",
            bottom: "0px",
          },
          topLeft: {
            width: "10px",
            height: "10px",
            border: "0.5px solid #777777",
            left: "0px",
            top: "0px",
          },
          topRight: {
            width: "10px",
            height: "10px",
            border: "0.5px solid #777777",
            right: "0px",
            top: "0px",
          },
        }
      : {};

위와 같이 작성한 후에 resizeHandleStyles에 넣어주었다.

 

왼쪽 위, 왼쪽 아래, 오른쪽 위, 오른쪽 위만 다음과 같이 스타일링 해주었다.

사진이 한 장이 아니라 여러 장이 존재하기 때문에
선택된 사진에만 나타나도록 하기 위해 selected === index 일때만 나타나도록 설정해주었다.

하나만 선택되는걸 볼 수 있다!

 

⭐️ 스크롤 시, 요소는 스크롤되지 않는 오류 발생

여기까지 수월하게 진행돼서 쉽다고 생각했었다.

다 잘되는데 화면을 스크롤하면 요소들이 같이 스크롤되지 않고 제자리에 있는 오류가 생겼다🙀

 

공식문서를 다시 잘 읽어보니

nearest node with position relative or absolute라고 나와있었다.

내가 지정해줬던 id=limit인 div 태그에 따로 position을 지정해주지 않은 것 같아서

div 태그에 position: "relative"를 추가해주니 오류가 해결되었다.

 

잘 동작하는걸 확인할 수 있다.

 

⭐️ 전체코드

import React, { useEffect, useRef, useState } from "react";
import { Rnd } from "react-rnd";
const Image = ({ image, initialPo, selected, changeSelected, index }) => {
  const handleClick = () => {
    changeSelected(index);
  };

  const handleStyles =
    selected == index
      ? {
          bottomLeft: {
            width: "10px",
            height: "10px",
            border: "0.5px solid #777777",
            left: "0px",
            bottom: "0px",
          },
          bottomRight: {
            width: "10px",
            height: "10px",
            border: "0.5px solid #777777",
            right: "0px",
            bottom: "0px",
          },
          topLeft: {
            width: "10px",
            height: "10px",
            border: "0.5px solid #777777",
            left: "0px",
            top: "0px",
          },
          topRight: {
            width: "10px",
            height: "10px",
            border: "0.5px solid #777777",
            right: "0px",
            top: "0px",
          },
        }
      : {};
  return (
      <Rnd
        default={{
          x: initialPo.x,
          y: initialPo.y,
          width: 100,
          height: 100,
        }}
        minWidth={50}
        minHeight={50}
        bounds="#limit"
        resizeHandleStyles={handleStyles}
        lockAspectRatio={true}
      >
        <img
          src={image}
          onClick={() => {
            handleClick(index);
          }}
          onTouchStart={() => {
            handleClick(index);
          }}
        />
      </Rnd>
]  );
};

export default Image;