프로젝트 코드리뷰/ITTY

리액트 스와이프(드래그 스크롤) 기능구현

SooHw 2023. 11. 21. 09:43
// 스크롤기능
  const scrollRef_port = useRef(null);
  const scrollRef_market = useRef(null);
  const [isDrag, setIsDrag] = useState(false); //드레그 중인지의 상태확인
  const [startX, setStartX] = useState(); //처음 클릭한 x좌표 
  const onDragStart_port = e => {
    e.preventDefault();
    setIsDrag(true);
    setStartX(e.pageX + scrollRef_port.current.scrollLeft);
  };
  const onDragStart_market = e => {
    e.preventDefault();
    setIsDrag(true);
    setStartX(e.pageX + scrollRef_market.current.scrollLeft);
  };


  const onDragEnd_port = () => {
    setIsDrag(false);
  };
  const onDragEnd_market = () => {
    setIsDrag(false);
  };
  const onDragMove_port = e => {
    if (isDrag) {
      const { scrollWidth, clientWidth, scrollLeft } = scrollRef_port.current;

      scrollRef_port.current.scrollLeft = startX - e.pageX;

      if (scrollLeft === 0) {
        setStartX(e.pageX); //가장 왼쪽일 때, 움직이고 있는 마우스의 x좌표가 곧 startX로 설정.
      } else if (scrollWidth <= clientWidth + scrollLeft) {
        setStartX(e.pageX + scrollLeft); //가장 오른쪽일 때, 움직이고 있는 마우스의 x좌표에 현재 스크롤된 길이 scrollLeft의 합으로 설정
      }
    }
  };
  const onDragMove_market = e => {
    if (isDrag) {
      const { scrollWidth, clientWidth, scrollLeft } = scrollRef_market.current;

      scrollRef_market.current.scrollLeft = startX - e.pageX;

      if (scrollLeft === 0) {
        setStartX(e.pageX); //가장 왼쪽일 때, 움직이고 있는 마우스의 x좌표가 곧 startX로 설정.
      } else if (scrollWidth <= clientWidth + scrollLeft) {
        setStartX(e.pageX + scrollLeft); //가장 오른쪽일 때, 움직이고 있는 마우스의 x좌표에 현재 스크롤된 길이 scrollLeft의 합으로 설정
      }
    }
  };
  // 쓰로틀 
  const throttle = (func, ms) => {
    let throttled = false;
    return (...args) => {
      if (!throttled) {
        throttled = true;
        setTimeout(() => {
          func(...args);
          throttled = false;
        }, ms);
      }
    };
  };

  const delay = 5;
  const onThrottleDragMove_port = throttle(onDragMove_port, delay);
  const onThrottleDragMove_market = throttle(onDragMove_market, delay);
  // 스크롤기능




<div className={style.port_list}
              onMouseDown={onDragStart_port}
              onMouseMove={isDrag ? onThrottleDragMove_port : null}
              onMouseUp={onDragEnd_port}
              onMouseLeave={onDragEnd_port}
              ref={scrollRef_port}>
              {portList.map((item) => <PortItem key={item._id} props={item} />)}
</div>

 

 

라이브러리 없이 시도한 드래그 스크롤 기능.

동작은 잘 된다. 스로틀 delay를 잘 조절해야 할듯.

 

기능을 구현 하고 보니 간편한 스와이프 라이브러리들이 매우 많았다..(swiper등)