프로젝트 정리/모현에서 모먹지

[모각코] 모현에서 모먹지?(2-2) - Home꾸미기:Slider(시간, 버튼, 드래그)

래모 2022. 8. 18. 01:33

Home 내부에 Slider을 만들어보자


AnimatePresence를 이용해서 이전에도 자주 만들었던 슬라이더 형태를 만들어주면 된다.

시간이 지나면 자동으로 넘어가도록 설정해주려고 한다.

 

1️⃣ Box 애니메이션 설정

일단 variants로 보이지 않을 때, 보일 때, 사라질때의 설정을 적어준다.

const roxVariants = {
    hidden: {
        x: 844,
    },
    visible: {
        x: 0,
    },
    exit: {
        x: -844,
    },
  };

body 자체의 width가 844px정도 되어서 x좌표를 그에 맞게 설정해주었다.

 

설정한 UI에서 한번에 보여지는 box의 개수는 2개이다.

따라서 offset을 2로 설정해준다.

아직 api 정보를 불러오지 못 했기 때문에 그냥 숫자 배열로 보여주게 하였다.

 

const [index, setIndex] = useState(0);
const [leaving, setLeaving] = useState(false);
const toggleLeaving = () => setLeaving((prev) => !prev);

...
<AnimatePresence initial = {false} onExitComplete={toggleLeaving}>
    <Row 
    variants={roxVariants}
    initial="hidden"
    animate="visible"
    exit="exit"
    transition={{ type: "tween", duration: 1 }}
    key = {index}
    >
        {[1,2,3,4,5,6].slice(offset * index, offset * index + offset)
        .map(i =>
        <Box >
            뭔가를 넣을겁니다{i}
        </Box>)}

    </Row>
...

 

애니메이션이 처음엔 실행이 되면 안 되기 때문에 initial을 false로 설정해준다.

onEixtComplete 속성은 버튼을 연속해서 누를시 애니메이션이 이상하게 작동되는 것을 막는다 

2️⃣ Bar 애니메이션 설정

슬라이더 밑에 동그라미가 인덱스에 따라 색을 바꿔서 넣고 싶다.

이걸 어떻게 구현해야 할지 고민하면서 이것저것 설정해봤는데 다음과 같이 결론이 났다.

 

1. Bar 안에 Circle 을 index만큼 넣기

2. Circle의 prop으로 num과 index를 넣어서 num === index일때 background-color변경하기

 

이게 가장 간단한 것 같다.

...
const Circle = styled(motion.div)`
	...
    background-color: ${(props)=> props.num === props.index ? props.theme.pointColor : "#B6B6B6"} ;
	...
`
...
<Bar>
    {[1,2,3].map(i => <Circle num = {i-1} index = {index}/>)}
</Bar>
</AnimatePresence>

 

3️⃣ 자동 슬라이드 

이제!! setInterval과 setIndex를 설정해줄것이다.

리액트에선 setInterval이 useEffect와 같이 사용되어서 정해진 시간마다 컴포넌트를 리렌더링 해준다.

useEffect(()=> {
    const loop = setInterval(() => {
        setIndex(prev => prev === 2? 0 : prev + 1);
    },7000)
    return () => {
        clearInterval(loop);
    };
},[])

 


만들고 팀원들이랑 이야기를 하다보니까 자동으로 슬라이드를 넘기는 것 대신에

화살표랑 드래그로 슬라이더를 관리하는게 더 좋을 것 같다고 판단되었다 

 

그래서!! 수정해보자

화살표로 관리

1️⃣ prev와 next버튼 만들기

const Prev = styled(motion.button)`
    font-size:30px;
    position: absolute ;
    height:200px;
    line-height:200px;
    top:50;
    color:${(props)=> props.theme.pointColor} ;
`
const Next = styled(Prev)`
    right:0;
`
...
<Prev><RiArrowLeftSLine/></Prev>
<Next><RiArrowRightSLine/></Next>

버튼에도 애니메이션을 넣어줄 거니까 motion으로 만든다

 

2️⃣ onClick으로 index관리하기

next를 누르면 index를 증가시키고 prev를 누르면 index를 감소시킬 것이다

또한 index가 max혹은 0 이 되면 처음으로 돌아가도록 해준다

 

...
const increaseIndex = () => {
    if (leaving) return;
    toggleLeaving();
    setBack(false);
    setIndex((prev) => (prev === 2 ? 0 : prev + 1));
};
const decreaseIndex = () =>{
    if (leaving) return;
    toggleLeaving();
    setBack(true);
    setIndex((prev) => (prev === 0 ? 2 :prev -1 ));
}
...
<Prev onClick = {decreaseIndex}><RiArrowLeftSLine/></Prev>
<Next onClick = {increaseIndex}><RiArrowRightSLine/></Next>

 

3️⃣ 애니메이션 넣기

그냥 hover시 scale만 좀 커지게 넣어줬다 별거없슴 ㅎㅎ...

<Prev onClick = {decreaseIndex} whileHover = {{scale:1.2}}><RiArrowLeftSLine/></Prev>
<Next onClick = {increaseIndex} whileHover = {{scale:1.2}}><RiArrowRightSLine/></Next>

드래그는 자고 나서 해보자...

 

드래그

1️⃣ 드래그 애니메이션 넣기 

드래그는 x방향으로만 해줄것이고 양 옆으로 제약을 줄것이다.

그리고 드래그 가능 요소에서 드래그를 놓을 때, 원점으로 다시 애니메이션을 넣어준다.

<Rox
...
drag = "x"
dragSnapToOrigin
dragConstraints = {{left:-100, right:100}}
...

 

 

2️⃣ 드래그의 범위에 따른 효과

onDragEnd를 통해 드래그가 끝났을 때 x좌표를 읽어내어서 

좌표의 크기에 따라 index를 변화시켜줄것이다.

onDragEnd={
    (info) => {
        if (info.point.x <= 500 ) {
            setBack(false);
            setIndex((prev) => (prev === 2 ? 0 : prev + 1));
        }
        if (info.point.x >= 800){
            setBack(true);
            setIndex((prev) => (prev === 0 ? 2 :prev -1 ));
        }
    }

범위는 직접 움직여서 적절한 숫자로 넣어주었다.

 

이러면 drag에 따른 슬라이더를 만들 수 있다.

뭔가 사아아아알짝 어색한거 같긴 한데... 암튼 완성 ㅎ.ㅎ