Carousel 도입이유
현재 프로젝트를 진행하면서 페이지가 너무 정적인 경향이 크다고 생각했습니다. 그래서 동적인요소를 추가하고자 했고 그 중에서도 대쉬보드에 Carousel을 도입하여 메인페이지에 동적인 느낌을 주려고 했습니다.
현재 사이트 모습
현재 메인페이지의 모습입니다. 화면 중앙에 위치한 대시보드에 Carousel을 도입해 자동으로 대쉬보드가 전환되고 또한 사용자가 화살표를 클릭하면 원하는 대쉬보드를 보여줄 수 있게 구현하고 싶습니다.
Carousel(캐러셀)이란?
캐러셀은 슬라이드쇼와 같은 방식으로 콘텐츠를 표시하는 UX구성요소입니다. 버튼을 눌러 옆으로 사진이 넘어가며 모션이 마치 회전목마와 비슷하다고 하여 붙여진 이름입니다. 캐러셀은 용도에 따라 자동재생되게 하거나, 사용자가 수동으로 넘기도록 구현할 수 있습니다.
대표적으로 넷플릭스 플랫폼의 화면에서 캐러셀을 볼 수 있습니다.
설계방법
저는 2가지의 요소를 만들고 하나의 요소만을 화면에 보여주도록 설계하겠습니다. 설계 순서를 작성해보겠습니다.
- HTML,CSS로 요소 만들기
- Previous와 Next 버튼을 만들어 클릭이벤트 생성
- 버튼을 클릭할때마다 transform : translateX()로 이동시켜주기
자세하게 풀어서 작성해보면 아래와 같습니다.
1) Container를 생성하여 2개의 버튼과 케러셀의 위치 조정( flex성질)
2) Wrapper를 생성하여 overflow:hidden 속성을 사용해 밖에 있는 이미지들이 아예 보이지 않게 설정(고정)
3) SlideWrapper에 ref를 지정해줘서 직접 dom 요소를 조작하도록 설정(x값이 움직임)
4) prev버튼, next버튼을 누르면 useState로 설정해둔 currentImgIdx값이 변경되도록 작성하고 useEffect()를 사용해 해당 state값이 변경될때마다 useRef로 지정한 slideRef의 translateX값이 변경되도록 작성
HTML,CSS 요소
먼저 대쉬보드에 보여줄 html 요소입니다. 하나씩 설명해보겠습니다.
return (
<Container>
<LeftBtn onClick={moveToPrevSlide}></LeftBtn>
<Wrapper>
<SlideWrapper ref={slideRef}>
<Dash >
<div className='dashboard-right'>
<div className='dashboard-title'>
<h1 style={{ fontWeight: "bold", fontSize: "50px", color:"blue" }}>Billim</h1>
</div>
<div style={{ marginTop: "20px" }} className='dashboard-decoration'>
<div style={{ marginBottom: "50px", fontSize:"30px" }}>
<p>언제어디서든지 상품을</p> <br/><p><span style={{color:"blue",fontSize:"35px",fontWeight:"bold"}}>대여</span> 해주고
<span style={{color:"blue",fontSize:"35px",fontWeight:"bold"}}> 대여</span> 받을 수 있는 서비스입니다.</p>
</div>
</div>
</div>
</Dash>
<Dash>
<div className='dashboard-right'>
<div className='dashboard-title'>
<h1 style={{ fontWeight: "bold", fontSize: "50px",color:"blue" }}>Billim</h1>
</div>
<div style={{ marginTop: "20px" }} className='dashboard-decoration'>
<div style={{ marginBottom: "50px", fontSize:"30px" }}><p>Billim이 처음이시라면?</p><br/><a>서비스 이용방법 보러가기</a></div>
</div>
</div>
</Dash>
</SlideWrapper>
</Wrapper>
<RightBtn onClick={moveToNextSlide}></RightBtn>
</Container>
)
Container는 단순히 버튼과 캐러셀의 위치를 배치하기 위함이고 Wrapper부터 실질적으로 케러셀의 영역입니다 즉, 사용자가 볼 수 있는 화면입니다. 창과 같다고 생각하면됩니다. 창에는 하나의 요소만 보여야 하기때문에 overflow:hidden 속성을 사용해야 합니다. 추가적으로 width, height를 설정하여 보여줄 크기를 설정합니다.
const Container = styled.div`
display:flex;
margin-left:200px;
`
const Wrapper = styled.div`
width:800px;
height:200px;
overflow:hidden;
margin:20px 80px;
`;
기본적으로 overflow:visible;속성이 적용되어 있습니다. hidden 속성을 적용하지 않으면 아래와 같이 보이게 됩니다.
즉 창에 해당하는 영역만 사용자에게 보여주어야 합니다. 그래서 그이외의 요소는 hidden속성을 주어 숨겨줘야합니다.
hidden 속성을 주게 되면 아래와 같이 보입니다.
다음으로 SlideWrapper에 대해 설명해보겠습니다. Slide Wrapper에 ref를 지정해줘 직접 dom요소를 조작하도록 해주었습니다.
const SlideWrapper = styled.div`
display:flex;
width:100%;
height:100%;
`;
Wrapper와 SlideWrapper가 햇갈릴 수 도 있는데 border로 확인해보면 빨간색 테두리가 Wrapper이고 파란색 테두리가 SlideWrapper입니다. 즉 다시 말해서 위치를 변경시켜줍니다.
마지막으로 Dash입니다. Dash는 단순히 대쉬보드에 대한 css입니다. 주의해야할점은 width와 height의 크기는 Wrapper의 width와 height와 같아야합니다. 같지 않으면 다음 dash가 미리보이거나 보이지 않을 수 있습니다. 그리고 현재 flex의 자식이기 때문에 flex:none을 사용해줘 독립적으로 나타나도록 합니다.
const Dash = styled.div`
width:800px;
height:200px;
flex: none; // 이 속성을 넣어야 화면에 1개씩 보여진다.
`;
state 및 클릭이벤트 생성
html, css 요소를 생성했으니 이제 왼쪽 오른쪽의 버튼을 클릭했을때 이미지가 넘어가도록 해보겠습니다.
- slideRef( useRef ) : Dom을 조작해 trans속성을 사용하기 위한
- currentImgIdx state : 현재 어떤 Dash를 보여주고 있는지 알기위한
- SlideRange : 현재 위치를 나타내는 값, currentImgIdx 값에 따라 없데이트
- moveToNextSlide() : 오른쪽화살표 눌렀을 때 실행되는 함수, 현재 0번째 대쉬보드이면 다음으로 마지막 대쉬보드이면 바로 return
- moveToPrevSlide() : 왼쪽화살표 눌렀을 때 실행되는 함수, 현재 1번째 대쉬보드이면 왼쪽으로 처음 대쉬보드이면 바로 return
- useEffect : currentImgIdx state가 변경되면 transform: translate() 속성을 이용해 동적으로 변경. x축 방향으로 -slideRange 픽셀 만큼이동.
const slideRef = useRef(null);
const [currentImgIdx, setCurrentImgIdx] = useState(0);
const IMG_WIDTH = 800;
const slideRange = currentImgIdx * IMG_WIDTH;
useEffect(() => {
slideRef.current.style.transition = "all 1s ease-in-out";
slideRef.current.style.transform = `translateX(-${slideRange}px)`;
}, [currentImgIdx]);
const moveToNextSlide = () => {
if (currentImgIdx == 1) return;
setCurrentImgIdx(currentImgIdx + 1);
}
const moveToPrevSlide = () => {
if (currentImgIdx == 0) return;
setCurrentImgIdx(currentImgIdx - 1);
};
실행화면
다음 포스팅에서는 일정 시간 간격마다 자동으로 슬라이드 되는 기능을 구현해보겠습니다.
'프론트엔드 > react' 카테고리의 다른 글
Billim 프로젝트 화면구성 (0) | 2023.12.09 |
---|---|
왜 react-query ? (3) | 2023.12.03 |
React. 최근본상품 - localStorage에 저장 (1) | 2023.10.06 |
리액트 - 서버에서 받은 UTC시간을 KST로 변환 (0) | 2023.09.15 |
React - navigate로 props전달방법 (0) | 2023.09.09 |