ํฐ์คํ ๋ฆฌ ๋ทฐ
Carousel Slide

Carousel Slide๋ ์ด๋ฒ WETCHAPEDIA ํ๋ก์ ํธ์์ ๋ด๊ฐ ๋งก์ ํต์ฌ ๊ธฐ๋ฅ์ด์ ๊ฐ์ฅ ๊ณ ๋ฏผํ๋ ๋ถ๋ถ์ด๋ค.
๋จ์ํ ๊ธฐ๋ฅ์ด ์ํํ๊ฒ ๋์๋๋ ๊ฒ ๋ฟ๋ง ์๋๋ผ ํด๋น ์ปดํฌ๋ํธ๋ฅผ ์ผ๋ง๋ ํจ์จ์ ์ผ๋ก ๋ง๋๋ ๊ฒ์ธ๊ฐ์ ๋ํด์ ๋์ ์์ด ๊ณ ๋ฏผํ์๊ธฐ์ ์ด์ ๋ํด์ ํฌ์คํ ํด๋ณด๊ณ ์ ํ๋ค.
์ฒ์์ Carousel Slide ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ ์ํด์ ์ผ์ ์์ญ์ Fixed View๋ก ์ง์ ํด ๋ ๋ค overflow value๋ฅผ hidden์ผ๋ก ํ์ฌ, ๋ฒํผ ์์๋ฅผ ๋๋ฅด๊ฒ ๋๋ฉด ํด๋น View์ ๋๋น๋งํผ transformX ๊ฐ์ ํผ์ผํธ(%) ๋จ์๋ก ์ด๋ํ๊ฒ๋ ํ์๋ค.
๊ทธ๋ฆฌ๊ณ Carousel Container ๋ด์ ๋ง์ฐ์ค๊ฐ hover๊ฐ ๋๋ฉด overflow value๋ฅผ scroll๋ก ๋ฐ๊พธ์ด, ์ฌ์ฉ์๊ฐ ์ผ๋ฐ ๊ฐ๋ก ์คํฌ๋กค์ผ๋ก๋ ๋ค์ํ UI๋ฅผ ํ์ธํ ์ ์๋๋ก ๊ธฐ๋ฅ์ ๊ตฌํํ์๋ค.
ํ์ง๋ง overflow์ value ๊ฐ์ ์ด๋ ๊ฒ ์ ๋์ ์ผ๋ก ๋ฐ๊พธ๋ค ๋ณด๋, ์ด์ ์ Feeds ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค์ง ๋ชป ํ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์๋ค.
๋์ณ๋๋ ์์๋ฅผ ์จ๊น ์ฒ๋ฆฌ๋ก ํ์๋ Container ๋ด์์ Slide Bar๋ฅผ X์ถ์ผ๋ก ๋์ด ๋น๊น์ผ๋ก์จ, ์จ๊ฒจ์ ธ ์๋ ๋๋จธ์ง ์์๋ค์ ๋ณผ ์ ์์๋ ๊ฒ์ธ๋ฐ, ์ผ๋ฐ ์คํฌ๋กค ์์ญ์ผ๋ก ๋ฐ๋๊ฒ ๋๋ฉด์ ์คํฌ๋กค ์์ ์ง์ ์ด์ ์ ์์๋ ํ์ธํ ์ ์๊ฒ ๋ ๊ฒ์ด๋ค.
์ด์ ์ด๋ฌํ ํ์์ ์ด๋ป๊ฒ ํด๊ฒฐํ ๊ฒ์ธ์ง ๊ณ ๋ฏผํ๋ค๊ฐ useRef()๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ํ์๋ค.
useRef()๋ querySelector()๋ getElementById()์ ๊ฐ์ด DOM์ ํน์ ์์์ ์ ๊ทผํ๋ค.
useRef()์ ์ด๋ฌํ ํน์ฑ์ ์ด์ฉํ๊ธฐ ์ํด์, Carousel Container ๋ด์์ ์์๋ฅผ ๋ด์ Slide Bar ๋ด๋น์ ์์์ ๊ธฐ๋ณธ overflow value๋ฅผ scroll๋ก ๊ฐ์ ์ค์ ํด์ค ๋ค ref๋ฅผ ์ง์ ํด ๋์๋ค.
<div ref={ref => (this.carouselSildeRef = ref)} />
๊ทธ๋ฆฌ๊ณ ๋ฒํผ ์์๋ฅผ ํด๋ฆญํ๊ฑฐ๋ ์ด๋ฒคํธ ๋ฐ์ ์, moveToX() ๋ผ๋ ์ฝ๋ฐฑ ํจ์๊ฐ ๋์๋๋๋ก ํ์๋ค.
moveToX๋ event.type ๊ฐ์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ๋์ํ๋ค.
ํด๋ฆญ ์ด๋ฒคํธ์ผ ๊ฒฝ์ฐ์๋ ํด๋น ์์ญ์ View ๋๋น๋งํผ ScrollLeft ๊ฐ์ ํ ๋นํ์ฌ ๋์ ์ผ๋ก ์ด๋ํ๋ ๊ฒ์ฒ๋ผ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ง๊ฒ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ์๋ค.
if (eventType === 'click') {
let { curTranslatePosX } = this.state;
let { name } = getTarget(event.target, 'carouselControl');
if (name === 'right') {
this.carouselSildeRef.scrollLeft = curTranslatePosX + slideMove;
this.setState({
curTranslatePosX: curTranslatePosX + slideMove,
});
} else {
this.carouselSildeRef.scrollLeft = curTranslatePosX - slideMove;
this.setState({
curTranslatePosX: curTranslatePosX - slideMove,
});
}
}
transform์ผ๋ก Slide Bar๋ฅผ ์์ง์ฌ ์คฌ๋ ๊ฒ๊ณผ๋ ๋ค๋ฅด๊ฒ(transform์ ์ค์ ๋ณด์ฌ์ง๋ ๊ฒ๊ณผ ๋ค๋ฅด๊ฒ layout์ ๋ณํจ์ด ์๊ธฐ ๋๋ฌธ์ ์ด์ ๊ฐ์ ์ฐธ์กฐํ ํ์์์ด 100% => 200% => 300% ... ์์ผ๋ก ๋์ํ๋ค) ์ด์ ์ ๊ฐ์ ์ฐธ์กฐํ ๋ค ํด๋น ๊ฐ์ ๊ฐ์ฐํ ๊ฐ๋งํผ ์คํฌ๋กค์ด ์์ง์ฌ์ผ ์ ์์ ์ผ๋ก ์ฌ๋ผ์ด๋ฉ ๊ธฐ๋ฅ์ด ๋์๋๊ธฐ ๋๋ฌธ์ Component ๋ด state ๊ฐ์ผ๋ก ์ง์์ ์ผ๋ก ์คํฌ๋กค ๋ ๊ธธ์ด๋ฅผ ์ ์ฌ ๋ฐ ๊ด๋ฆฌํด์ฃผ์๋ค.
๊ทธ๋ฆฌ๊ณ ๋ง์ฝ์ event.type์ด Click์ด ์๋ Scroll์ผ ๊ฒฝ์ฐ์๋ ๋ณ๋์ ์ด๋ ์ฐ์ฐ์ ํ์ง ์๊ณ ์ดํ ํด๋ฆญ ์ด๋ฒคํธ ์ ์ฌ๋ผ์ด๋ ๋ฐ์ ์ ํํ ์ด๋์ ์ํด์ ์คํฌ๋กค ๋ ์๋ง์ ์์ state ๊ฐ์ ์ ์ฅํด ์ฃผ๋ ๋ก์ง๋ง์ ์์ฑํ์๋ค.
else {
let curScrollLeftPos = event.target.scrollLeft;
this.setState({ curTranslatePosX: curScrollLeftPos });
}
๊ธฐ๋ฅ ์์ฒด๋ ์กฐ๊ธ๋ง ๊ณ ๋ฏผ์ ํด๋ณธ๋ค๋ฉด ๊ทธ๋ฆฌ ์ด๋ ค์ด ์ฌํญ์ ์๋์์ง๋ง, ๊ธฐ๋ฅ ์์ฒด์ ์ธ ๊ฒ๋ณด๋ค ๋๋ฅผ ๋ ๊ณ ๋ฏผํ๊ฒ ํ๋ ๊ฒ์ ํด๋น ์ปดํฌ๋ํธ๋ฅผ ๋ ๋ฆฝ์ ์ธ ํ๋์ ๋ชจ๋๋ก์ ์๋ํ๊ฒ๋ ๋ค๋ฅธ ์ปดํฌ๋ํธ์์ ๊ด๊ณ๋ฅผ ์ค์ ํ๊ณ ๋ด๋ถ ๋ก์ง์ ์ต๋ํ ๋ฒ์ฉ์ฑ ์๊ฒ ๋์ํ๋๋ก ์์ฑํ๋ ์ผ์ด์๋ค.
์ฆ, Carousel Slide Component๋ฅผ Common Component๋ก์ ์ฌ์ฉ๋ ์ ์๋๋ก ๋ชฉํํ์๊ณ ์ด๋ฅผ ์ํด ๋ค์๊ณผ ๊ฐ์ ์ฌํญ์ ๋ก์ง์ ๋ฐ์ํ์๋ค.
์ฒซ ๋ฒ์งธ, Carousel Slide Bar์ ๋ค์ด๊ฐ๋ Feeds(์ํ ๊ด๋ จ ์ ๋ณด๋ค)๋ค์ Mappingํ์ฌ ํ๋์ ์ํ ๊ฐ๋ฅํ ๋ฆฌ์คํธ ์๋ฃ ๊ตฌ์กฐ์ธ ๋ฐฐ์ด๋ก ๋ง๋ค์ด ์ค ๋ค, ์ด๋ฅผ CarouselSlide Components ๋ด ul ์์๋ก style ๊ฐ์ ์ง์ ํ Container ๋ด์ ๋ฐ์ธ๋ฉ ์์ผฐ๋ค.
์ด๋ฐ ์์ผ๋ก Component ๋ด๋ถ์ ์๋ ๋ฆฌ์คํธ ๊ฐ์ children ๊ฐ์ผ๋ก ์ ๋์ ์ผ๋ก ํ ๋น ๋ฐ์์ผ๋ก์จ, ํด๋น ์ปดํฌ๋ํธ์ ํ์ฅ์ฑ์ ์ฆ๋์์ผฐ๋ค.
<div
ref={ref => (this.carouselSildeRef = ref)}
className="feedsCarousel"
onScroll={this.moveToX}
style={{ width: { slideWidth } }}
>
<ul className="carouselSlider">{children}</ul> //children์ Mapping๋ ํ๋์ ๋ฆฌ์คํธ์ด๋ค.
( ... )
๊ทธ ๋ค์์ผ๋ก CarouselSlide Component ๋ด์ Fixed ๋ View์ ๊ฐ์ ํ๋ฉด ํฌ๊ธฐ์ ๋ฐ๋ผ ์ ๋์ ์ผ๋ก ๋ฐ๊ฟ์ฃผ๊ธฐ ์ํ์ฌ slideWidth์ slideMove ๋ ๊ฐ์ props๋ฅผ ์ค์ ํด์ฃผ์ด ๋ค๋ฅธ page ๋ด์์ ๊ฐ๋ณ ๋ ํ๋ฉด์๋ ํด๋น Carousel Bar์ ์ฌ์ด์ฆ์ ์์ง์ด๋ ์ ๋๊ฐ ๋น์จ๋๋ก๋ง์ถฐ์ง๋๋ก ๋ก์ง์ ์์ฑํ์๋ค.
<CarouselSlide slideWidth={1320} slideMove={1327}>
<MovieList type={feedsType} movieListData={movies} />
</CarouselSlide>
// slideWidth๋ ์ค์ View ํฌ๊ธฐ, slideMove๋ ์ค์ ์คํฌ๋กค์ด ์์ง์ฌ์ผ ๋ ์์ง์(margin ๋ฐ padding ๊ฐ์ด ํฌํจ๋์ด ์๊ธฐ ๋๋ฌธ์ ์ค์ View๋ณด๋ค ์กฐ๊ธ ๋ ์์ง์ด๋๋ก ์กฐ์ )์ ์ ๋์ด๋ค.
๋ง๋ฌด๋ฆฌ
์ด๋ฒ ํ๋ก์ ํธ๋ฅผ ํตํด CarouselSlide Component๋ฅผ ๋ง๋ค์ด๋ณด๋ฉด์, ๋ฆฌ์กํธ ๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ์ฌ์ฉํ๋๊ฐ์ ๋ํด์ ๋ค์ ํ๋ฒ ์๊ฐํ๊ฒ ๋์๋ค.
ํ๋ก๊ทธ๋จ์ ๋จ์ํ input๊ณผ output๋ง ์ ๋๋ก ๋์ค๊ธฐ๋ง ํ๋ ๋จ์ ์ฐ์ฐ ์ฅ์น๊ฐ ์๋๋ค.
ํ๋ก๊ทธ๋จ์ ๋ด์์๋ ์ ๋ง์ ๊ธฐ๋ฅ๋ค์ด ์ฝํ ๋ค์ํ ์์ ๋ค์ด ์ํ๋๋ค. ๊ทธ ์์์ ๊ณตํต๋ ์งํฉ์ ์ฐ์ฐ์ ํตํด ๋์ผํ ์ฐ์ฐ ๊ณผ์ ์ ๋จ์ํ์ํฌ ์ ์๋ ๊ฒ์ธ๊ฐ์ ๋ํด์ ๋์ ์์ด ์๊ฐํด์ผ ํ๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
์ง๊ธ์ ์์ฃผ ์์ ํ๋ก์ ํธ์ด์ง๋ง ํฅํ ํ์ ์ ๋๊ฐ์ ๊ท๋ชจ๊ฐ ์๋ ํ๋ก์ ํธ์ ์ฐธ๊ฐํ ๋ ํ ๊ฐ์ธ์ผ๋ก์ ๋ด๊ฐ ์ด๋ฌํ ๋๊ท๋ชจ์ ์์ ์ฅ์์ ๊ณตํํ ์ ์๋ ๊ฒ์ ๊ฑฐ๋ํ๊ณ ๋๋จํ ์ผ์ด ์๋, ๋ค์ํ ํ๋ก์ธ์ค๋ค์ ์ ๋ชฉ์ํฌ ์ ์๋ ํ๋์ ์์ ๋ชจ๋์ ๋ง๋ค์ด์ ๊ฑฐ์์ ์ผ๋ก ํ๋ก์ ํธ์ ํจ์จ์ฑ ์ฆ๋์ํฌ ์ ์๋๋ก ํ๋ ๊ฒ์ด ์๋๊น ๋ผ๋ ์๊ฐ์ด ๋ค์๋ค.
์ด๋ฒ CarouselSlide Component๋ฅผ ๋ง๋ค๊ณ ๋ถ๋ฆฝ์์ผ ๋ด์ผ๋ก์จ ์ด๋ฌํ ์ ๋ค์ ๊นจ๋ฌ์ ์ ์์๋ค.
๊ด๋ จ ํฌ์คํ
https://choi95.tistory.com/175
Carousel Slide ๊ธฐ๋ฅ Component๋ก ๋ถ๋ฆฝ
Issue ์ Carousel Slide ๊ธฐ๋ฅ์ ํด๋น Main Page ๋ฟ๋ง ์๋๋ผ ๋ค๋ฅธ Page ๋ด์์๋ ์ฐ์ด๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ์ปดํฌ๋ํธ๋ก ๋ถ๋ฆฝํ ํ์๊ฐ ์์์ ํ์ธํ์๋ค. Carousel Slide ๊ธฐ๋ฅ์ด ๋ฆฌ์คํธ ํ์์์ ์ ๋๋ก ๋์ํ๊ธฐ
choi95.tistory.com
https://choi95.tistory.com/176
Type ๊ฐ์ ๋ฐ๋ผ ์กฐ๊ฑด๋ถ ๋๋๋ง_getDerivedStateFromProps
https://choi95.tistory.com/175 Carousel Slide ๊ธฐ๋ฅ Component๋ก ๋ถ๋ฆฝ Issue ์ Carousel Slide ๊ธฐ๋ฅ์ ํด๋น Main Page ๋ฟ๋ง ์๋๋ผ ๋ค๋ฅธ Page ๋ด์์๋ ์ฐ์ด๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ์ปดํฌ๋ํธ๋ก ๋ถ๋ฆฝํ ํ์๊ฐ ์์์ ํ..
choi95.tistory.com