이미지 슬라이드의 원리라면 컨테이너 요소에 사용할 이미지 width를 지정
해놓고 row 요소에서
flex를 사용하여 하위 요소들을 가로로 나열 시킨 후 width를 이미지 갯수만큼 퍼센트를 지정
해주면 아래와 같이 나열된다.
그 후, width가 지정된 컨테이너에 overflow: hidden
을 선언해주면 하나의 이미지만 보이게 된다.
여기서 이미지를 옮길 때는 자바스크립트를 이용하여 row요소의 margin-left 값을 조정
해주면 슬라이드를 구현할 수 있다.
.img-slider-container {
width: 300px;
height: 200px;
border-radius: 15px;
overflow: hidden;
}
.img-slider-container .img-slider-row {
display: flex;
width: 300%; /* 이미지 갯수에 따라 지정 */
height: 100%;
margin-left: 0%;
transition: margin 0.5s;
}
.img-slider-container .img-slider-col {
width: 100%;
height: 100%;
}
.img-slider-col img {
object-fit: cover;
width: 100%;
height: 100%;
}
// for img slider
const sliderContainers = document.querySelectorAll('.img-slider-container');
class Slider {
constructor(target){
this.sliderContainer = target;
this.dots = [...this.sliderContainer.querySelectorAll(".dot")];
this.sliderRow = target.querySelector('.img-slider-row');
this.imgLength = target.querySelectorAll('.img-slider-col').length * 100 - 100;
this.sliderRow.style.width = `${this.imgLength + 100}%`;
this.curPosition = 0;
this.onEvent();
}
moveSlider(e) {
const isMinMaxSlider = () => this.curPosition > this.imgLength || this.curPosition < 0;
if(e.target.className.includes('prev')){
this.curPosition-= 100;
this.toggleBtn();
if(isMinMaxSlider()) this.curPosition = 0;
this.toggleDot(this.curPosition);
this.sliderRow.style.marginLeft = `-${this.curPosition}%`;
} else if(e.target.className.includes('next')){
this.curPosition+= 100;
this.toggleBtn();
if(isMinMaxSlider()) this.curPosition = this.imgLength;
this.toggleDot(this.curPosition);
this.sliderRow.style.marginLeft = `-${this.curPosition}%`;
}
}
onEvent(){
// 요소가 아닌 해당 class 인스턴스 바인딩
this.sliderContainer.addEventListener('click', this.moveSlider.bind(this));
}
toggleBtn() {
const prev = this.sliderContainer.querySelector('.prev');
const next = this.sliderContainer.querySelector('.next');
const isMax = () => this.curPosition === this.imgLength;
if(this.curPosition === 0){
prev.style.visibility = 'hidden';
next.style.visibility = 'visible';
} else if (isMax()){
prev.style.visibility = 'visible';
next.style.visibility = 'hidden';
} else {
prev.style.visibility = 'visible';
next.style.visibility = 'visible';
}
}
toggleDot(value) {
this.dots.map( (dot, idx) => {
if(idx === (value / 100)) return dot.classList.add("active");
dot.classList.remove("active");
});
};
}
[...sliderContainers].map(sliderContainer => new Slider(sliderContainer));
function moveSlider(e){
console.log(e.target);
}
sliderContainer.addEventListener('click', moveSlider);
각 버튼에 일일이 이벤트리스너를 해주지 않아도 버블링을 이용하여 이전, 다음 버튼등에 대한 이벤트 핸들링을 할 수 있다.
슬라이드는 이전에 만들어본 경험이 있어서 크게 막히는 부분은 없었다. 아직 인터랙션에서 부족한 부분이 많지만 이번 클론코딩은 HTML, CSS 위주로 하기때문에 다음 화면을 만들어 볼 예정이다.