이번 시간은 슬라이드 버튼을 이미지 내부에 보이도록 하고, 닷 버튼 대신 썸네일 이미지를 추가하였습니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>07. 슬라이드 이펙트</title>
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/slider.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>
</head>
<body class="img09 bg08 font02">
<header id="header">
<h1>Javascript Slider Effect07</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>
</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:ebmdols@naver.com">ebmdols@naver.com</a>
</footer>
<!-- //footer -->
</body>
</html>
object-fit
object-fit 속성은 이미지나 비디오와 같은 대체 콘텐츠를 표시할 때, 해당 콘텐츠를 포함하는 요소의 크기에 맞게 조정하거나 자르는 방법을 제어하는 데 사용됩니다. 이 속성은 CSS의 background-size 속성과 유사한 역할을 합니다.
fill: 대체 콘텐츠를 요소의 크기에 맞게 늘리거나 축소합니다. 가로세로 비율이 유지되지 않으며, 콘텐츠가 찌그러질 수 있습니다.
contain: 대체 콘텐츠가 요소의 크기 내에 완전히 들어가도록 늘립니다. 콘텐츠의 원래 가로세로 비율이 유지됩니다.
cover: 대체 콘텐츠가 요소의 크기를 완전히 덮도록 늘립니다. 콘텐츠의 원래 가로세로 비율이 유지됩니다.
none: 대체 콘텐츠를 요소의 크기에 맞게 조정하지 않습니다. 대신, 콘텐츠의 원래 크기를 유지합니다.
scale-down: none과 contain 중 적용할 수 있는 가장 작은 값을 사용합니다. 대체 콘텐츠가 요소의 크기를 초과하지 않도록 늘립니다.
opacity는 CSS 속성 중 하나로, 해당 요소의 투명도를 조절하는 데 사용됩니다. opacity 값은 0과 1 사이의 실수 값으로 지정할 수 있으며, 0은 요소가 완전히 투명하다는 것을 의미하고, 1은 요소가 완전히 불투명하다는 것을 의미합니다.
transparent는 CSS 색상 값 중 하나로, 투명한 색상을 나타내는 키워드입니다.
ease-in-out은 CSS 애니메이션 타이밍 함수 중 하나로, 처음과 끝 부분에서는 느리게 시작하고 끝나며, 중간 부분에서는 빠르게 진행되는 이징(easing) 함수입니다. 이징 함수는 CSS 애니메이션에서 애니메이션의 속도를 제어하는 데 사용됩니다.
<script>
let images = [
"img/sliderEffect06-min.jpg",
"img/sliderEffect07-min.jpg",
"img/sliderEffect08-min.jpg",
"img/sliderEffect09-min.jpg",
"img/sliderEffect10-min.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<thumna]ilNodes.length; i++){
// thumnailNodes[i].addEventListener("click", function(){ //그냥 함수는 this를 가져올 수 있음
// 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(function(el, index){
el.addEventListener("click", function(){
slider.thumnails.querySelector("img.active").classList.remove("active")
el.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")
thumnailNodes[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")
thumnailNodes[currentIndex].classList.add("active")
//썸네일
thumnailNodes[currentIndex].classList.add("active");
});
//오른쪽 버튼 클릭하기
slider.nextBtn.addEventListener("click", function(){
imageNodes[currentIndex].classList.remove("active")
thumnailNodes[currentIndex].classList.remove("active")
//1 2 3 4 0 1 2 3...
currentIndex = (currentIndex + 1) % images.length
imageNodes[currentIndex].classList.add("active")
//썸네일
thumnailNodes[currentIndex].classList.add("active");
})
}
imageSlider(document.querySelector(".slider__wrap"), images);
</script>
변수 images에 이미지들을 배열로 저장합니다.
함수 imageSlider에 매개변수 parent와 images를 넣어줍니다.
그 안에 선택자를 객체로 저장하여 줍니다.
이미지들과 썸네일 이미지, 이전 버튼, 다음 버튼을 위한 선택자를 만들었습니다.
이미지를 출력하기 위해 배열로 저장되어 있는 images를 map() 메서드를 사용하여 불러줍니다.
return `<img src="${image}" alt="이미지${index}">` 이미지 태그의 이미지 주소에는 slider.images.innerHTML 가 순서대로 반복적으로 들어가고 alt에는 map()메서드의 키 값 index가 차례로 들어갑니다.
let imageNodes = slider.images.querySelectorAll("img"); 코드는 slider 객체의 images 프로퍼티에서 img 요소를 모두 선택하여 imageNodes 변수에 할당합니다.
다음으로, imageNodes[currentIndex].classList.add("active") 코드는 imageNodes 변수에서 현재 인덱스(currentIndex)에 해당하는 img 요소에 active 클래스를 추가합니다. 이를 통해 현재 이미지를 활성화합니다.
그리고, slider.thumnails.innerHTML = slider.images.innerHTML; 코드는 slider 객체의 images 프로퍼티에 있는 이미지들을 slider 객체의 thumnails 프로퍼티에 있는 요소에 복사하여 출력합니다. 이를 통해 이미지와 동일한 순서의 썸네일을 생성합니다.
마지막으로, let thumnailNodes = slider.thumnails.querySelectorAll("img"); 코드는 slider 객체의 thumnails 프로퍼티에서 img 요소를 모두 선택하여 thumnailNodes 변수에 할당합니다.
thumnailNodes[currentIndex].classList.add("active"); 코드는 thumnailNodes 변수에서 현재 인덱스(currentIndex)에 해당하는 img 요소에 active 클래스를 추가합니다. 이를 통해 현재 썸네일을 활성화합니다.
slider.thumnails.innerHTML = slider.images.innerHTML; 코드는 slider 객체의 images 프로퍼티에 있는 이미지들을 slider 객체의 thumnails 프로퍼티에 있는 요소에 복사하여 출력합니다. 이를 통해 이미지와 동일한 순서의 썸네일을 생성합니다.
//왼쪽 버튼 클릭하기
if(currentIndex < 0) currentIndex = images.length - 1; 코드는 currentIndex 변수가 0보다 작아지면 images.length - 1로 설정하여 마지막 이미지로 이동합니다.
imageNodes[currentIndex].classList.add("active") 코드는 업데이트된 currentIndex에 해당하는 이미지(imageNodes[currentIndex])에 active 클래스를 추가합니다.
thumnailNodes[currentIndex].classList.add("active") 코드는 업데이트된 currentIndex에 해당하는 썸네일 이미지(thumnailNodes[currentIndex])에 active 클래스를 추가합니다.
//오른쪽 버튼 클릭하기
(currentIndex + 1) % images.length 코드는 currentIndex 변수에 1을 더한 뒤 images.length로 나눈 나머지 값을 반환하여, 이미지 배열을 순환하며 슬라이더를 동작시킵니다.
imageNodes[currentIndex].classList.add("active") 코드는 업데이트된 currentIndex에 해당하는 이미지(imageNodes[currentIndex])에 active 클래스를 추가합니다.
thumnailNodes[currentIndex].classList.add("active") 코드는 업데이트된 currentIndex에 해당하는 썸네일 이미지(thumnailNodes[currentIndex])에 active 클래스를 추가합니다.