“ 지연되는 프로젝트에 인력을 더 투입하면 오히려 더 늦어진다. ”
- Frederick Philips Brooks
Mythical Man-Month 저자
슬라이더 이펙트 썸네일 슬라이드(버튼, 썸네일)
💜 슬라이더 이펙트 07
슬라이드 이펙트 7번째 썸네일 입니다.
head
<!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">
css 파일을 링크로 연결시켜줘 따로 작업했습니다.
reset.css와 slider.css는 전에 했던 파일과 동일합니다
확인을 원하시면 아래 링크를 통해 확인해주세요
style
<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%, 150px);
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>
slider__img 는 이미지 슬라이더의 이미지를 감싸는 컨테이너이다
이것은 상대적인 위치를 사용하여 크기 및 위치를 조정
이 컨테이너는 overflow:hidden 속성을 사용해
이미지가 넘침을 방지
이미지는 position:absolute 속성을 사용해 컨테이너 내에서 정렬
transtion 속성은 이미지의 페이드인 및 페이드아웃을 적용하는데 사용
slider__thumb는 슬라이더 아래에 위치하는 썸네일 이미지를 감싸는 컨테이너이다
이것은 상대적인 위치를 사용해 크기 및 위치를 조정
transform 속성은 이 컨테이너를 수평으로 이동해 슬라이더 이미지와 정렬
slider__btn은 이전 및 다음 버튼을 감싸는 컨테이너다
이것은 position:absolute 속성을 사용해 슬라이더 위에 위치한다.
a 태그는 버튼을 만들기 위해 사용되며 justify-content 및 align-itmes 속성을 사용해 버튼 내부의 텍스트를 수평 및 수직으로 가운데 정렬한다.
transition 속성은 버튼의 배경색상이 변화하는데 사용
HTML
<body class="img09 bg01 font09">
<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:hunmi961119@gmail.com">hunmi961119@gmail.com</a>
</footer>
<!-- //footer -->
header와 main, footer의 구역을 나눠 작업해줍니다.
scrpt
<script>
let images = [
"img/sliderEffect07-min.jpg",
"img/sliderEffect02-min.jpg",
"img/sliderEffect04-min.jpg",
"img/sliderEffect05-min.jpg",
"img/sliderEffect06-min.jpg"
];
원래는 위에 HTML에서 이미지를 넣어줬었는데
이번엔 script에 사진을 넣어작업해주겠습니다.
script에서 사진을 넣을 때는 배열을 사용해 넣어주겠습니다.
선택자
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")
}
부모 요소와 이미지 배열을 받아서, 슬라이더를 생성하고 제어하는 기능을 수행하는 함수입니다.
함수 내부에서는 currentIndex 라는 변수를 초기화 하고, 슬라이더에서 사용할 요소들을 선택합니다.
이때 parent 매개변수로 전달받은 요소를 기준으로 querySelecotr() 메서드를 사용해 필요한 요소를 선택
slider 객체는 다섯 개의 프로퍼티를 가지고 있습니다.
parnet 슬라이더 요소의 부모 요소
imges 슬라이더 이미지를 보여주는 div 요소
thumnails 슬라이더의 썸네일 이미지를 보여주는 div 요소
prevBtn 이전 이미지 보기 버튼을 나타내는 a 요소
nextBtn 다음 이미지 보기 버튼을 나타내는 a 요소
이미지, 썸네일
//이미지 출력하기
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");
parent 슬라이더가 추가될 부모 요소를 나타낸다.
images 슬라이더에 사용될 이미지들의 경로가 담긴 배열
images.innerHTML slider__img 클래스를 가진 요소의 내부 HTML을 image 배열의 요소들을 이용해 동적으로 생성
Array.map() 메서드를 사용해 img 태그를 생성, Array.join()메서드를 사용해 imahes 배열의 요소들을 문자열로 결합
thumnails.innerHTML slider__thumb 클래스를 가진 요소의 내부 HTML 을 slider__img 클래스를 가진 요소의 내부 HTML 과 같게 설정
imageNodes[currentIndex].classList.add("active") currentIndex 에 해당하는 imageNodes 배열의 요소에 active클래스를 추가
thumnailNode[currentIndex].classList.add("active") currentIndex 에 해당하는 thumnailNodes 배열의 요소에 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");
});
}
썸네일 이미지를 클릭했을 때 해당 이미지가 활성화 되도록 하는 이벤트 리스너를 등록하는 부분
for 루프를 사용해 thumnailNodes 배열에 잇는 모든 썸네일 이미지에 대해 클릭 이벤트를 등록
각 이벤트 리스너는 클릭한 썸네일 이미지를 찾고, 이전에 활성화된 썸네일 이미지에 active 클래스를 제거하고, 현재 클릭한 썸네일 이미지에 active 클래스를 추가
그리고 이미지 노드 배열에 현재 인덱스에 해당하는 이미지에도 active 클래스를 제거하고, 클릭한 썸네일 이미지의 인덱스로 currnetIndex 값을 업데이트 한 다음, 새로운 currentIndex 값에 해당하는 이지 노드에 active 클래스를 추가
forEach문
thumnailNodes.forEach((el,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");
});
});
forEach 메소드는 배열의 요소마다 주어진 함수를 호출
이 함수는 현재 요소, 요소 인덱스, 배열 전체를 인수로 받는다
따라서 이전 for루프를 forEach 로 대체하여 요소와 인덱스를 사용해 작동하는 콜백 함수를 작성할 수 있다.