<section class="gallery">
<h2>Gallery</h2>
<ul class="box__gallery">
<li>
<a href="https://picsum.photos/id/237/500/300">
<img src="https://picsum.photos/id/237/150/150" alt="이미지1"></li>
</a>
<li>
<a href="https://picsum.photos/id/238/500/300">
<img src="https://picsum.photos/id/238/150/150" alt="이미지2"></li>
</a>
<li>
<a href="https://picsum.photos/id/239/500/300">
<img src="https://picsum.photos/id/239/150/150" alt="이미지3"></li>
</a>
<li>
<a href="https://picsum.photos/id/240/500/300">
<img src="https://picsum.photos/id/240/150/150" alt="이미지4"></li>
</a>
<li>
<a href="https://picsum.photos/id/241/500/300">
<img src="https://picsum.photos/id/241/150/150" alt="이미지5"></li>
</a>
<li>
<a href="https://picsum.photos/id/242/500/300">
<img src="https://picsum.photos/id/242/150/150" alt="이미지5"></li>
</a>
</div>
</section>
<div class="slide-overlay">
<button class="close-btn">close</button>
<button class="slide-btn --prev">
prev
</button>
<button class="slide-btn --next">
next
</button>
<div class="slide__container">
<ul class="slides">
<li><img src="" alt="이미지1"></li>
<li><img src="" alt="이미지2"></li>
<li><img src="" alt="이미지3"></li>
<li><img src="" alt="이미지4"></li>
<li><img src="" alt="이미지5"></li>
<li><img src="" alt="이미지6"></li>
</ul>
</div>
</div>
/* 갤러리 썸네일들 */
.box__gallery {
width: 1200px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
/* //슬라이드 팝업창 */
.slide-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.8);
display: none;
}
.slide__container {
position: absolute;
width: 500px;
height: 300px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
overflow: hidden;
}
.slides {
width: 600%;
position: relative;
left: 0;
}
.slides::after {
content: "";
display: block;
clear: both;
}
.slides > li {
float: left;
}
/* 슬라이드 버튼 */
.slide-btn {
position: absolute;
width: 100px;
height: 100px;
border-radius: 50%;
border: none;
background-color: white;
cursor: pointer;
top: 50%;
transform: translateY(-50%);
z-index: 9;
}
.--prev {
left: 20%;
}
.--next {
right: 20%;
}
/* 닫기버튼 */
.close-btn {
position: absolute;
padding: 1em;
top: 2em;
right: 15%;
}
/* bullet */
#bullets {
position: absolute;
bottom: 20%;
left: 50%;
transform: translateX(-50%);
}
#bullets > li {
float: left;
margin: 0 8px;
}
#bullets > li > a {
display: block;
text-decoration: none;
color: transparent;
width: 1em;
height: 1em;
background-color: rgb(165, 165, 165);
border-radius: 50%;
transition: 0.2s;
}
#bullets > li > a.on {
background-color: tomato;
}
const overlay = document.querySelector(".slide-overlay");
let slides = document.querySelectorAll(".slides > li");
let slidePhoto = document.querySelectorAll(".slides > li>img");
const slide = document.querySelector(".slides");
const thumbnails = document.querySelectorAll(".box__gallery > li");
const photoCount = slides.length;
const duration = 400;
let bullets = 0;
let photoIndex = 0;
// 갤러리 모달창 이벤트
thumbnails.forEach((thumbnail) => {
thumbnail.addEventListener("click", (e) => {
e.preventDefault();
overlay.style.display = "block";
// 썸네일 원본 사진과 갤러리 슬라이드 이미지 소스 링크 연결
for (let i = 0; i < thumbnails.length; i++) {
let photo = thumbnails[i].lastElementChild;
slidePhoto[i].src = photo.href;
}
});
});
document.querySelector(".close-btn").addEventListener("click", () => {
overlay.style.display = "none";
});
// bullet 이미지 개수에 맞게 생성하는 함수
function createBullets() {
// bullet들의 리스트를 생성
const bulletsList = document.createElement("ul");
bulletsList.setAttribute("id", "bullets");
overlay.appendChild(bulletsList);
// 이미지 개수대로 bullet를 생성
slides.forEach((slide, index) => {
const a = document.createElement("a");
a.setAttribute("href", "#");
// 이미지의 index를 a의 html에 집어넣음 (나중에 이미지 이동할 때 주소 역할이 되어줌)
a.innerHTML = `${index}`;
const li = document.createElement("li");
li.appendChild(a);
bulletsList.appendChild(li);
});
return (bullets = document.querySelectorAll("#bullets > li > a"));
}
createBullets();
bulletLink();
// bullet을 클릭하면 해당하는 번호의 이미지로 슬라이드 되는 함수
function bulletLink() {
bullets.forEach((bullet, index) => {
bullet.addEventListener("click", (e) => {
e.preventDefault();
// 클릭된 bullet의 인덱스
const clickedIndex = index;
// 현재 bullet과 클릭된 bullet의 차이
let step = clickedIndex - photoIndex;
photoIndex = clickedIndex;
//모든 bullet의 클래스를 없애고 클릭된 bullet에만 on 클래스 추가
bulletClassReset();
bullets[clickedIndex].classList.add("on");
// 클릭할 때마다 순서가 바뀌는 slides들 업뎃
slides = document.querySelectorAll(".slides>li")
let currentSlides = [slides];
//step이 양수: 현재 요소보다 뒤에 오는 요소로 이동
if (step > 0) {
// 이미지 슬라이드 step의 수 만큼 앞에서 자른다
let sliceSlides = currentSlides.slice(undefined, step);
slide.style.transition = duration+"ms";
slide.style.left=step * -100+"%";
window.setTimeout(() => {
slide.removeAttribute("style");
// 잘린 요소들을 맨 뒤로 집어넣기..
slide.append(sliceSlides);
}, duration);
} else {
// step이 음수: 현재 요소보다 앞에 있는 요소로 이동
sliceSlides = currentSlides.slice(step);
// 잘린 요소들을 맨 앞으로 집어넣기
slide.prepend(sliceSlides);
slide.style.left = step * 100 + "%";
window.setTimeout(()=>{
slide.style.left = 0;
slide.style.transition = duration+"ms";
})
}
//서로 같은 경우 이동할 필요가 없기 때문에 함수 즉시 종료
if (step==0) return;
});
});
}
//썸네일을 클릭하면 해당하는 사진으로 점프
thumbnails.forEach((thumbnail, index) => {
// 클릭 이벤트 추가
thumbnail.addEventListener("click", (e) => {
e.preventDefault();
const clickedIndex = index;
let step = clickedIndex - photoIndex;
photoIndex = clickedIndex;
bulletClassReset();
bullets[clickedIndex].classList.add("on");
// 클릭할 때마다 순서가 바뀌는 slides들 업뎃
slides = document.querySelectorAll(".slides>li");
let currentSlides = [slides];
if (step > 0) {
// 이미지 슬라이드 step의 수 만큼 앞에서 자른다
let sliceSlides = currentSlides.slice(undefined, step);
// 잘린 슬라이드들 맨 뒤로 집어넣기..
slide.append(sliceSlides);
} else {
sliceSlides = currentSlides.slice(step);
// 잘린 슬라이드들 맨 앞으로 집어넣기
slide.prepend(sliceSlides);
}
});
});
// 슬라이드 버튼 클릭 이벤트
document.querySelector(".--next").addEventListener("click", nextSlideImage);
document.querySelector(".--prev").addEventListener("click", prevSlideImage);
// 다음 사진으로 슬라이드
function nextSlideImage() {
photoIndex++;
photoIndex %= photoCount;
slide.style.left = "-100%";
slide.style.transition = duration + "ms";
window.setTimeout(() => {
slide.appendChild(slide.firstElementChild);
slide.removeAttribute("style");
}, duration);
bulletClassReset();
//해당하는 bullet에 on 클래스 넣기
bulletIndex();
}
// 이전 사진으로 슬라이드
function prevSlideImage() {
photoIndex--;
photoIndex %= photoCount;
slide.insertBefore(slide.lastElementChild, slide.firstChild);
slide.style.left = "-100%";
slide.style.transition = "0ms";
window.setTimeout(() => {
slide.style.left = 0;
slide.style.transition = duration+"ms";
});
bulletClassReset();
//해당하는 bullet에 on 클래스 넣기
bulletIndex();
}
// 모든 bullet의 on 클래스를 삭제
function bulletClassReset() {
bullets.forEach((bullet) => {
bullet.classList.remove("on");
});
}
//해당하는 bullet에 on 클래스 넣기
function bulletIndex() {
// photoIndex가 음수일 때를 고려
let index = photoIndex + bullets.length;
index %= bullets.length;
bullets[index].classList.add("on");
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.