슬라이드 이펙트 일곱번째
HTML
<body class="img05 bg05 font05">
<header id="header">
<h1>Javascript Slider Effect03</h1>
<p>슬라이드 이펙트 : 썸네일 슬라이드(버튼, 썸네일)</p>
<ul>
<li><a href="sliderEffect01.html">1</a></li>
<li><a href="sliderEffect02.html">2</a></li>
<li><a href="sliderEffect03.html">3</a></li>
<li><a href="sliderEffect04.html">4</a></li>
<li><a href="sliderEffect05.html">5</a></li>
<li><a href="sliderEffect06.html">6</a></li>
<li class="active"><a href="sliderEffect07.html">7</a></li>
<li><a href="sliderEffect08.html">8</a></li>
</ul>
</header>
<!-- header -->
<main id="main">
<div class="slider__wrap">
<div class="slider__img"></div>
<div class="slider__thumb"></div>
<div class="slider__btn">
<a href="#" class="prev" title="이전이미지">prev</a>
<a href="#" class="next" title="다음이미지">next</a>
</div>
</div>
</main>
<!-- main -->
<footer id="footer">
<a href="mailto:kshkmn0929@naver.com">kshkmn0929@naver.com</a>
</footer>
<!-- footer -->
CSS
<style>
/* slider__wrap */
.slider__wrap {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 800px;
height: 450px;
box-shadow: 0 50px 100px rgba(0, 0, 0, 0.4);
}
.slider__img {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
.slider__img img {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
opacity: 0;
transform: scale(1.1);
transition: all 500ms ease-in-out;
}
.slider__img img.active {
opacity: 1;
transform: scale(1);
}
.slider__thumb {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, 140px);
width: 100px;
display: flex;
justify-content: center;
gap: 10px;
}
.slider__thumb img {
cursor: pointer;
border: 2px solid transparent;
}
.slider__thumb img.active {
border: 2px solid #fff;
}
.slider__btn a{
position: absolute;
top: 0;
width: 40px;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 12px;
color: #fff;
background-color: rgba(0, 0, 0, 0.2);
transition: all 300ms ease-in-out;
}
.slider__btn a.next {
right: 0;
}
.slider__btn a:hover {
background-color: rgba(0, 0, 0, 0.5);
}
</style>
JAVASCRIPT
<script>
// 선택자
let images = [
"./img/Effect_bg01.jpg",
"./img/Effect_bg02.jpg",
"./img/Effect_bg03.jpg",
"./img/Effect_bg04.jpg",
"./img/Effect_bg05.jpg"
]
function imageSlider(parent, images){
let currentIndex = 0;
// 선택자
let slider = {
parent: parent,
images: parent.querySelector(".slider__img"),
thumnails: parent.querySelector(".slider__thumb"),
prevBtn: parent.querySelector(".slider__btn .prev"),
nextBtn: parent.querySelector(".slider__btn .next")
}
// 이미지 출력하기
slider.images.innerHTML = images.map((image, index) => {
return `<img src="${image}" alt="이미지${index}">`
}).join("");
// 이미지 활성화(active)하기
let imageNodes = slider.images.querySelectorAll("img");
imageNodes[currentIndex].classList.add("active");
// 썸네일 이미지 출력하기
slider.thumnails.innerHTML = slider.images.innerHTML;
// 썸네일 활성화(active)하기
let thumnailNodes = slider.thumnails.querySelectorAll("img");
thumnailNodes[currentIndex].classList.add("active");
// 썸네일 이미지 클릭하기
// for(let i=0; i<thumnailNodes.length; i++){
// thumnailNodes[i].addEventListener("click", function(){
// slider.thumnails.querySelector("img.active").classList.remove("active");
// thumnailNodes[i].classList.add("active");
// imageNodes[currentIndex].classList.remove("active");
// currentIndex = i;
// imageNodes[currentIndex].classList.add("active");
// });
// }
thumnailNodes.forEach((el,index) => {
el.addEventListener("click", function(){
slider.thumnails.querySelector("img.active").classList.remove("active");
thumnailNodes[index].classList.add("active");
imageNodes[currentIndex].classList.remove("active");
currentIndex = index;
imageNodes[currentIndex].classList.add("active");
})
});
// 왼쪽 버튼 클릭하기
slider.prevBtn.addEventListener("click", function(){
imageNodes[currentIndex].classList.remove("active");
currentIndex--;
//0 4 3 2 1 0 4 3....
if(currentIndex < 0) currentIndex = images.length -1;
imageNodes[currentIndex].classList.add("active");
// 썸네일
slider.thumnails.querySelector("img.active").classList.remove("active");
thumnailNodes[currentIndex].classList.add("active")
});
// 오른쪽 버튼 클릭하기
slider.nextBtn.addEventListener("click", function(){
imageNodes[currentIndex].classList.remove("active");
//1 2 3 4 0 1 2 3 4.....
currentIndex = (currentIndex + 1) % images.length;
imageNodes[currentIndex].classList.add("active");
// 썸네일
slider.thumnails.querySelector("img.active").classList.remove("active");
thumnailNodes[currentIndex].classList.add("active")
});
}
imageSlider(document.querySelector(".slider__wrap"), images);
</script>
JAVASCRIPT 설명
images 배열: 이미지 경로가 저장된 배열입니다.
imageSlider() 함수: 슬라이더를 만드는 함수입니다. 인자로는 슬라이더를 감싸는 부모 요소와 이미지 경로를 저장한 images 배열을 받습니다.
slider 객체: 슬라이더를 구성하는 요소들을 저장한 객체입니다. parent는 슬라이더를 감싸는 부모 요소를, images는 이미지를 출력할 요소를, thumnails는 썸네일을 출력할 요소를, prevBtn과 nextBtn은 이전/다음 버튼 요소를 나타냅니다.
slider.images.innerHTML: images 배열에 저장된 이미지 경로를 바탕으로 이미지를 출력합니다. map() 메서드를 사용하여 이미지 태그를 문자열로 변환하고 join() 메서드로 문자열을 연결합니다. 결과적으로 이미지 요소들이 slider.images 요소의 innerHTML로 설정됩니다.
imageNodes[currentIndex].classList.add("active"): 현재 이미지에 active 클래스를 추가하여, 활성화된 이미지를 나타냅니다.
slider.thumnails.innerHTML: 이미지 출력 부분과 동일한 방식으로, images 배열에 저장된 이미지 경로를 바탕으로 썸네일을 출력합니다.
thumnailNodes[currentIndex].classList.add("active"): 현재 썸네일에 active 클래스를 추가하여, 활성화된 썸네일을 나타냅니다.
thumnailNodes.forEach(): 각 썸네일 요소에 click 이벤트를 등록합니다. 클릭 시, 이전 활성화된 썸네일에 있던 active 클래스를 제거하고, 클릭한 썸네일에 active 클래스를 추가합니다. 이전에 활성화된 이미지에 있는 active 클래스를 제거하고, 현재 클릭한 썸네일의 인덱스에 해당하는 이미지에 active 클래스를 추가합니다.
slider.prevBtn.addEventListener(): 이전 버튼에 click 이벤트를 등록합니다. 클릭 시, 이전에 활성화된 이미지에 있던 active 클래스를 제거하고, currentIndex를 하나 감소시킵니다. currentIndex가 0보다 작아지면, images 배열의 마지막 인덱스로 currentIndex를 설정합니다. 이전 이미지에 active 클래스를 추가합니다. 마지막으로, 이전에 활성화된 썸네일에 있던 active 클래스를 제거하고, 현재 currentIndex에 해당하는 썸네일에 active 클래스를 추가합니다.
마지막으로 이미지 슬라이더를 구현하는 함수 imageSlider에서, 오른쪽 버튼(.slider__btn .next)이 클릭되었을 때의 동작을 구현하고 있습니다.
버튼을 클릭하면 현재 활성화(active)된 이미지를 비활성화 시키고(imageNodes[currentIndex].classList.remove("active")), 다음 이미지를 활성화 시킵니다(imageNodes[currentIndex].classList.add("active")).
이때, currentIndex는 현재 활성화된 이미지의 인덱스를 나타냅니다. currentIndex를 (currentIndex + 1) % images.length으로 설정하는 이유는, 이미지 배열 images의 마지막 이미지에서 다음 버튼을 클릭하면 첫번째 이미지로 돌아가기 위해서입니다.
그리고 마지막으로, 썸네일(thumbnail) 이미지도 활성화(active) 상태를 갱신해줍니다. 현재 활성화된 썸네일 이미지의 active 클래스를 삭제하고(slider.thumnails.querySelector("img.active").classList.remove("active")), 다음 이미지의 썸네일 이미지에 active 클래스를 추가해줍니다(thumnailNodes[currentIndex].classList.add("active")).