슬라이드의 늪에 빠진 나...
하하 즐겁다.
더 제대로 만들었다면 더 즐거웠을 텐데...?
어쨌든 리액트로 슬라이드 만들기 시작~
생각한 로직
- 슬라이더 안의 요소의 사이즈에 기반하여 이동한다.
- 다음/이전 버튼을 누르면 슬라이드 요소를 감싸는 박스를 이동시킨다.
- 위치가 0이면 이전 버튼 미노출
- 슬라이드 요소를 감싸는 박스의 사이즈가 위치 값이랑 같으면 미노출(하지만 이 부분은 개선이 필요..)
작업 설명
현재 슬라이드의 위치를 담을 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 |