본문 바로가기
프로젝트/2024

리액트로 슬라이드 만들기 2 + typescript

by dev__log 2024. 4. 4.

슬라이드의 늪에 빠진 나...

하하 즐겁다. 

 

더 제대로 만들었다면 더 즐거웠을 텐데...?

어쨌든 리액트로 슬라이드 만들기 시작~

 

생각한 로직

  1. 슬라이더 안의 요소의 사이즈에 기반하여 이동한다.
  2. 다음/이전 버튼을 누르면 슬라이드 요소를 감싸는 박스를 이동시킨다. 
  3. 위치가 0이면 이전 버튼 미노출
  4. 슬라이드 요소를 감싸는 박스의 사이즈가 위치 값이랑 같으면 미노출(하지만 이 부분은 개선이 필요..)

 

작업 설명

현재 슬라이드의 위치를 담을 state를 만든다.

const [position, setPosition] = useState(0);

 

 

슬라이드로 이동할 값을 정한다.

354 부분은 슬라이드 요소 1개의 가로 사이즈이고, 16은 오른쪽 마진의 값이다.

값을 합해서 370이라고 해도 되지만 각 값의 구분을 위해 일부러 저렇게 했다.

const MOVE_POINT = 354 + 16; //임시값

 

(이 부분은 개선이 필요하지만 개발해야 하는 시안이 화면의 사이즈에 딱 맞게 나눠서 들어가는 게 아니라 넘치는 부분은 그냥 잘리게 보이는 시안이라서 당장은 괜찮지만 이렇게 값을 관리하는 건 좋지 않다.)

 

 

이전 버튼을 누르면 현 위치 값 + 이동할 값, 다음 버튼을 누르면 - 이동할 값

  const onClickPrevHandler = () => {
    if (position < 0) {
      setPosition((prev) => prev + MOVE_POINT);
    }
  };

  const onClickNextHandler = () => {
    setPosition((prev) => prev - MOVE_POINT);
  };

 

 

css로 transform:translateX로 슬라이드를 이동시킨다. 

그리고 부드러운 이동을 위해서 transition을 사용했다. 

 

sort 부분은 좋아요를 많이 받은 순으로 보여줘야 해서 sort로 내림차순 정렬을 했다. 

<div className="relative flex overflow-hidden">
        <ul
          className="flex flex-nowrap"
          style={{
            transition: "all 0.4s ease-in-out",
            transform: `translateX(${position}px)`
          }}
        >
          {data
            ?.sort((a, b) => {
              return b.likeList.length - a.likeList.length;
            })
            .map((item) => {
              const likedLength = item.likeList.length;

              return (
                <li key={item.boardId} className="w-[356px] p-4 mr-4 border border-solid border-slate-300 list-none rounded-[2rem]">
                  <div className="flex items-center">
                    <span className="w-5 h-5 flex overflow-hidden rounded-full bg-slate-200">
                      {item.userInfo.userImage && <Image src={item.userInfo.userImage} alt={item.userInfo.nickname!} width={20} height={20} />}
                    </span>
                    {item.userInfo.nickname}
                  </div>
                  <Link href={`/community/${item.boardId}`} className="block text-ellipsis whitespace-nowrap overflow-hidden">
                    {item.boardTitle}
                  </Link>
                  <div className="mt-4 text-right">
                    댓글 {item.comment.length} 좋아요 {likedLength}
                  </div>
                </li>
              );
            })}
        </ul>
        <div>
          {position !== ((data?.length as number) - 1) * -MOVE_POINT && (
            <button type="button" className="absolute right-0 top-1/2 -translate-y-1/2 w-9 h-9 rounded-full bg-black text-white" onClick={onClickNextHandler}>
              NEXT
            </button>
          )}
          {position !== 0 && (
            <button type="button" className="absolute left-0 top-1/2 -translate-y-1/2 w-9 h-9 rounded-full bg-black text-white" onClick={onClickPrevHandler}>
              PREV
            </button>
          )}
        </div>
      </div>

 

 

개선해야 할 부분

일단은 이렇게 구현했지만.. 나는 마지막 요소 차례가 되면 컨테이너의 끝 부분에 위치했으면 한다. 

그리고 아까 상수로 관리하던 값도 더 나은 방법을 찾고 싶다. 

 

 

결과

 

'프로젝트 > 2024' 카테고리의 다른 글

[react] 탭 메뉴 만들기  (0) 2024.04.16
최종 팀 프로젝트 Day9  (0) 2024.04.05
최종 팀 프로젝트 Day8  (0) 2024.04.04
최종 팀 프로젝트 Day7  (1) 2024.04.04
리액트로 슬라이드 만들기 + typescript  (2) 2024.04.03