์บ๋ฌ์ ์ ์ด๋ฏธ์ง ์ปฌ๋ ์ ์ด๋ ๊ธฐํ ์ฝํ ์ธ ๋ฅผ ์ฌ๋ผ์ด๋์ผ ํ์์ผ๋ก ํ์ํ๋ ๋ฐ ์ฌ์ฉ๋๋ ์ธ๊ธฐ ์๋ ์น ๋์์ธ ์์์ ๋๋ค.
HTML, CSS ๋ฐ JavaScript๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ ์บ๋ฌ์ ์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์บ๋ฌ์ ์ HTML ๊ตฌ์กฐ๋ถํฐ ์์ํ๊ฒ ์ต๋๋ค.
<div class="carousel-container">
<div class="carousel-slide">
<img src="https://picsum.photos/id/870/536/354" alt="Dummy Image">
<img src="https://picsum.photos/id/537/536/354" alt="Dummy Image">
<img src="https://picsum.photos/id/1060/536/354" alt="Dummy Image">
</div>
<button class="carousel-prev">prev</button>
<button class="carousel-next">next</button>
</div>
์ด ์ฝ๋๋ ์ธ ๊ฐ์ ์ด๋ฏธ์ง๋ฅผ ํ์ํ๋ ๊ธฐ๋ณธ ์บ๋ฌ์ ๋๋ ์ด๋ฏธ์ง ์ฌ๋ผ์ด๋์ฉ์ ๋๋ค.
carousel-container
ํด๋์ค๊ฐ ์๋ ์ปจํ
์ด๋ div
๋ก ์์ํฉ๋๋ค.carousel-slide
ํด๋์ค๊ฐ ์๋ div
๊ฐ ์์ต๋๋ค.img
์์๊ฐ ์์ต๋๋ค.div
๋ค์ carousel-prev
๋ฐ carousel-next
ํด๋์ค๊ฐ ์๋ ๋ ๊ฐ์ ๋ฒํผ ์์๊ฐ ์์ต๋๋ค.์ด์ HTML ๊ตฌ์กฐ๋ฅผ ๊ฐ์ถ์์ผ๋ฏ๋ก ๋ช ๊ฐ์ง ๊ธฐ๋ณธ CSS๋ฅผ ์ถ๊ฐํ์ฌ ์บ๋ฌ์ ์ ์คํ์ผ์ ์ง์ ํ๊ฒ ์ต๋๋ค.
.carousel-container {
position: relative;
width: 536px;
height: 354px;
overflow: hidden;
}
.carousel-slide {
display: flex;
height: 100%;
}
.carousel-slide img {
width: 536px;
height: 354px;
object-fit: cover;
}
.carousel-prev,
.carousel-next {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 50px;
height: 50px;
background-color: skyblue;
color: white;
border: none;
border-radius: 30%;
outline: none;
cursor: pointer;
}
.carousel-prev {
left: 0;
}
.carousel-next {
right: 0;
}
์์ ๋ณด์ฌ๋๋ฆฐ ์บ๋ฌ์ ์ฝ๋์ CSS ์คํ์ผ์ ๋๋ค.
.carousel-container
ํด๋์ค์๋ ์๋ ์์น๊ฐ ์ง์ ๋์ด ๋ฐฐ์น๋ ํ์ ์์๊ฐ ์ด ์ปจํ
์ด๋์ ๊ด๋ จํ์ฌ ๋ฐฐ์น๋ ์ ์์ต๋๋ค.overflow: hidden
์ ์ปจํ
์ด๋ ํฌ๊ธฐ๋ฅผ ์ด๊ณผํ๋ ์ฝํ
์ธ ๋ฅผ ์จ๊ธฐ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค..carousel-slide
ํด๋์ค๋ ์ด๋ฏธ์ง๊ฐ ์ผ๋ ฌ๋ก ํ์๋๋๋ก flex
, ์ปจํ
์ด๋ ๋์ด๋ฅผ ์ฑ์ฐ๋๋ก height 100%
๋ก ํ์๋ฉ๋๋ค..carousel-slide img
ํด๋์ค๋ ๋ชจ๋ ์ด๋ฏธ์ง๊ฐ ๋์ผํ ํฌ๊ธฐ๋ฅผ ๊ฐ๋๋ก ๊ณ ์ ๋ ๋๋น์ ๋์ด๊ฐ ์ ๊ณต๋ฉ๋๋ค. object-fit: cover
๋ ์ด๋ฏธ์ง๊ฐ ์ปจํ
์ด๋๋ฅผ ์์ ํ ๋ฎ๋๋ก ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค..carousel-prev
๋ฐ .carousel-next
ํด๋์ค๋ carousel ์ปจํ
์ด๋์ ์๋์ ์ผ๋ก ๋ฐฐ์น๋๋๋ก position: absolute
๋ก ์คํ์ผ์ด ์ง์ ๋ฉ๋๋ค.transform: translateY(-50%)
๋ ๋ฒํผ์ ์์ง์ผ๋ก ์ค์์ ๋ฐฐ์นํฉ๋๋ค.์ด์ ์บ๋ฌ์ ์ด ์๋ํ๋๋ก ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ถ๊ฐํ๊ฒ ์ต๋๋ค.
const carouselSlide = document.querySelector(".carousel-slide");
const carouselImages = document.querySelectorAll(".carousel-slide img");
const prevButton = document.querySelector(".carousel-prev");
const nextButton = document.querySelector(".carousel-next");
let counter = 1;
const size = 536;
carouselSlide.style.transform = `translateX(${-size}px)`;
nextButton.addEventListener("click", () => {
if (counter >= carouselImages.length - 1) return;
carouselSlide.style.transition = "transform 0.4s ease-in-out";
counter++;
carouselSlide.style.transform = `translateX(${-size * counter}px)`;
});
prevButton.addEventListener("click", () => {
if (counter <= 0) return;
carouselSlide.style.transition = "transform 0.4s ease-in-out";
counter--;
carouselSlide.style.transform = `translateX(${-size * counter}px)`;
});
carouselSlide.addEventListener("transitionend", () => {
if (carouselImages[counter].id === "lastClone") {
carouselSlide.style.transition = "none";
counter = carouselImages.length - 2;
carouselSlide.style.transform = `translateX(${-size * counter}px)`;
}
if (carouselImages[counter].id === "firstClone") {
carouselSlide.style.transition = "none";
counter = carouselImages.length - counter;
carouselSlide.style.transform = `translateX(${-size * counter}px)`;
}
});
์ด ์ฝ๋๋ ์บ๋ฌ์ ์ ๋์์ ์ ์ดํ๊ณ ํ์ ๋ฒํผ์ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง๋ฅผ ์ผ์ชฝ์ด๋ ์ค๋ฅธ์ชฝ์ผ๋ก ์ด๋ํ ์ ์์ต๋๋ค.
์ฝ๋์ ์ฒ์ ๋ ์ค์ ์บ๋ฌ์ ์ฌ๋ผ์ด๋ ์ปจํ ์ด๋์ ๊ทธ ์์ ๋ชจ๋ ์ด๋ฏธ์ง๋ฅผ ์ ํํ๊ณ ๋ณ์์ ์ ์ฅํฉ๋๋ค.
๋ค์ ๋ ์ค์ ๊ฐ๊ฐ ์ด์ ๋ฒํผ๊ณผ ๋ค์ ๋ฒํผ์ ์ ํํ์ฌ ๋ณ์์ ์ ์ฅํฉ๋๋ค.
์นด์ดํฐ ๋ณ์๋ 1๋ก ์ด๊ธฐํ๋๊ณ ํฌ๊ธฐ ๋ณ์๋ ์บ๋ฌ์ ์ปจํ ์ด๋์ ๋๋น๋ก ์ค์ ๋ฉ๋๋ค.
์บ๋ฌ์ ์ฌ๋ผ์ด๋๋ ํ ์ด๋ฏธ์ง ๋๋น๋งํผ ์ผ์ชฝ์ผ๋ก ์ด๋ํ์ฌ ๋ ๋ฒ์งธ ์ด๋ฏธ์ง๊ฐ ์ฒ์์ ๋ณด์ ๋๋ค.
๋ค์ ๋ฒํผ ํด๋ฆญ์ ์์ ํ๊ธฐ ์ํด nextButton ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์ถ๊ฐ๋์์ต๋๋ค.
์นด์ดํฐ ๋ณ์๊ฐ ์ด๋ฏธ์ง์ ๋์ ๋๋ฌํ๋์ง ํ์ธํ๊ณ ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ์นด์ดํฐ ๋ณ์๋ฅผ ์ฆ๊ฐ์ํค๊ณ ์บ๋ฌ์
์ฌ๋ผ์ด๋๋ฅผ ํ ์ด๋ฏธ์ง ๋๋น๋งํผ ์ผ์ชฝ์ผ๋ก ์ด๋ํฉ๋๋ค.
์ด์ ๋ฒํผ์ ํด๋ฆญ์ ์์ ํ๊ธฐ ์ํด prevButton ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์ถ๊ฐ๋์์ต๋๋ค.
์นด์ดํฐ ๋ณ์๊ฐ ์ด๋ฏธ์ง์ ์์ ๋ถ๋ถ์ ์๋์ง ํ์ธํ๊ณ ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ ์นด์ดํฐ ๋ณ์๋ฅผ ๊ฐ์์ํค๊ณ ์บ๋ฌ์ ์ฌ๋ผ์ด๋๋ฅผ ํ ์ด๋ฏธ์ง ๋๋น๋งํผ ์ค๋ฅธ์ชฝ์ผ๋ก ์ด๋ํฉ๋๋ค.
carouselSlide ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ carouselSlide์ CSS ์ ํ์ด ์๋ฃ๋ ๋ ์คํ๋๋ transitionend
์ด๋ฒคํธ๋ฅผ ์์ ํฉ๋๋ค.
ํ์ฌ ์ด๋ฏธ์ง๊ฐ ๋ง์ง๋ง ๋ณต์ ๋ณธ์ด๋ฉด ์ ํ์ด ์ ๊ฑฐ๋๊ณ ์นด์ดํฐ๋ ๋ง์ง๋ง์์ ๋ ๋ฒ์งธ ์ด๋ฏธ์ง ์์น๋ก ์ค์ ๋ฉ๋๋ค.
ํ์ฌ ์ด๋ฏธ์ง๊ฐ ์ฒซ ๋ฒ์งธ ๋ณต์ ๋ณธ์ด๋ฉด ์ ํ์ด ์ ๊ฑฐ๋๊ณ ์นด์ดํฐ๊ฐ ๋ง์ง๋ง ์ด๋ฏธ์ง ์์น๋ก ์ค์ ๋ฉ๋๋ค.
์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ์ฌ ๋ค์ํ ๋์์ธ์ ๋ค๋ฅธ ์บ๋ฌ์ ์ ์ ์ํ ์ ์์ต๋๋ค.
์๋ ํ์ธ์, ์ ๋ก๋ฒ ์ด์ค ํ๋ก ํธ์๋์ค์ฟจ ๋ฉํ ์ ๋๋ค. ์์ฑํด์ฃผ์ ๊ธ ์ ์ฝ์์ต๋๋ค!
๊ฐ์ฌํฉ๋๋ค :)