# 15.멀티플슬라이드

In 

# 목차

  • 1. 멀티플 슬라이드
    • 1.1. [준비] 구조작성
      • 1.1.1. HTML
      • 1.1.2. CSS
    • 1.2. [1단계] 변수초기화
      • 1.2.1. JS
    • 1.3. [2단계] 복사본 생성
      • 1.3.1. cloneSlide
    • 1.4. [3단계] 슬라이드 배치
      • 1.4.1. slideLayout
      • 1.4.2. setSlidePos
    • 1.5. [4단계] autoPlay
      • 1.5.1. MoveSlide1
      • 1.5.2. MoveSlide2
    • 1.6. [5단계] 이벤트별 재생제어
      • 1.6.1. intervalId 할당
      • 1.6.2. clearInterval 작성
      • 1.6.3. 이벤트핸들러 작성
    • 1.7. [6단계] control
      • 1.7.1. 변수초기화
      • 1.7.2. 이벤트핸들러 작성
    • 1.8. [8단계] pager
      • 1.8.1. 동적요소 추가
      • 1.8.2. 페이저 이벤트 작성
    • 1.9. 반응형작성
      • 1.9.1. 변수 초기화
      • 1.9.2. 작성
    • 1.10. 디버깅

# 1. 멀티플 슬라이드

미리보기
https://qwerewqwerew.github.io/source/jq/15/multi.html

# 1.1. [준비] 구조작성

# 1.1.1. HTML

<!DOCTYPE html>
<html lang="ko">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>Document</title>
		<link rel="stylesheet" href="multi.css" />
	</head>

	<body>
		<div class="container">
			<div class="slide_wrapper">
				<ul class="slides">
					<li>슬라이드01</li>
					<li>슬라이드02</li>
					<li>슬라이드03</li>
					<li>슬라이드04</li>
					<li>슬라이드05</li>
				</ul>
				<div class="controls"><span class="prev">prev</span><span class="next">next</span></div>
				<div class="pager"></div>
			</div>
		</div>
		<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
		<script src="multi.js"></script>
	</body>
</html>

# 1.1.2. CSS

* {
	margin: 0;
	padding: 0;
}
li {
	list-style: none;
}
.container {
	width: 660px;
	margin: 100px auto;
	overflow: hidden;
}

.slide_wrapper {
	position: relative;
	width: 660px;
	overflow: hidden;
	padding-top: 200px;
	margin: auto;
}
.slides {
	position: absolute;
	left: 0;
	top: 0;
	width: 100%;
	height: 200px;
}
.slides li {
	position: absolute;
	width: 200px;
	height: 200px;
	background: #ccc;
}
.controls {
	text-align: center;
	margin-top: 50px;
}
.controls span {
	background: #be8856;
	color: #fff;
	padding: 10px 20px;
	margin: 0 10px;
	display: inline-block;
}

.pager {
	list-style: none;
	display: flex;
	justify-content: space-between;
	font-size: 2em;
}

# 1.2. [1단계] 변수초기화

# 1.2.1. JS

const slideWrapper = $('.slide_wrapper'); //최상위 부모
const slides = slideWrapper.find('.slides'); // 이동할요소 (li의 부모 ul)
const slide = slides.find('li'); // li 슬라이드
const slideCount = slide.length; //슬라이드의 총 갯수
const slideWidth = slide.width(); //li 각각 너비
const slideGap = 30; // li간격
let currentIdx = 0; //초기값
let moveAmt; //slideWidth+slideGap 이동거리
let newSlides; //새 슬라이드 목록을 저장할 변수

# 1.3. [2단계] 복사본 생성

# 1.3.1. cloneSlide

cloneSlide()

cloneSlide();
function cloneSlide() {
	slides.append(slide.clone().addClass('clone'));
	slides.prepend(slide.clone().addClass('clone'));
}

# 1.4. [3단계] 슬라이드 배치

# 1.4.1. slideLayout

slideLayout(slideWidth, slideGap);
function slideLayout(sw, sm) {
	//li 가로배치
	newSlides = $('.slide_wrapper li');
	moveAmt = sw + sm;
	newSlides.each(function (idx) {
		$(this).css({ left: moveAmt * idx + 'px', width: sw + 'px' });
	});
}

# 1.4.2. setSlidePos

ul 중앙정렬

setSlidePos()

function setSlidePos() {
	const ulMoveAmt = -moveAmt * slideCount;
	slides.css({ transform: `translateX(${ulMoveAmt}px)` });
}

# 1.5. [4단계] autoPlay

# 1.5.1. MoveSlide1

//이동함수
function moveSlide() {
	currentIdx++;
	if (currentIdx > slideCount) {
		slides.css('left', 0); //애니메이트 효과를 적용하지 않고 왼쪽으로 이동
		currentIdx = 0;
	}
	console.log(currentIdx);
	console.log(moveAmt); //230
	slides.stop().animate({ left: moveAmt * -currentIdx }, 500);
}
setInterval(() => {
	moveSlide();
}, 650);

# 1.5.2. MoveSlide2

애니메이트 메서드의 콜백함수를 활용하여 작성

function moveSlideCb(n) {
	slides.stop().animate({ left: moveAmt * -n }, 500, function () {
		if (currentIdx > slideCount) {
			slides.css('left', 0);
			currentIdx = 0;
		} else if (currentIdx < -(slideCount - 1)) {
			console.log(moveAmt * slideCount);
			slides.css('left', -moveAmt * slideCount);
			currentIdx = slideCount;
		}
	});
	currentIdx = n;
}
setInterval(() => {
	moveSlideCb(currentIdx + 1); //반복문이 아니므로 ++ 은 계속 0이 됨
}, 650);

# 1.6. [5단계] 이벤트별 재생제어

# 1.6.1. intervalId 할당

setInterval 을 이벤트 발생시 정지 시키자

let timer = undefined;
function autoSlide() {
	timer = setInterval(() => {
		moveSlideCb(currentIdx + 1); //반복문이 아니므로 ++ 은 계속 0이 됨
	}, 650);
}
autoSlide();

# 1.6.2. clearInterval 작성

function stopSlide() {
	clearInterval(timer);
	timer = undefined;
}

# 1.6.3. 이벤트핸들러 작성

slideWrapper.mouseenter(function () {
	stopSlide();
});
slideWrapper.mouseleave(function () {
	autoSlide();
});

# 1.7. [6단계] control

# 1.7.1. 변수초기화

const prevBtn = slideWrapper.find('.prev');
const nextBtn = slideWrapper.find('.next');

# 1.7.2. 이벤트핸들러 작성

nextBtn.on('click', function () {
	moveSlideCb(currentIdx + 1);
});
prevBtn.on('click', function () {
	moveSlideCb(currentIdx - 1);
});

# 1.8. [8단계] pager

# 1.8.1. 동적요소 추가

const pager = $('.pager');
let pagerHTML = '';
slide.each(function (i) {
	pagerHTML += '<a href="#">' + (i + 1) + '</a>';
});
pager.html(pagerHTML);

# 1.8.2. 페이저 이벤트 작성

pager.find('a').click(function (e) {
	e.preventDefault();
	let i = $(this).index();
	MoveSlide(i);
});

# 1.9. 반응형작성

# 1.9.1. 변수 초기화

const maxSlides = 3;
let responsiveGap = 20;
let responseSlideWidth; //윈도우 리사이징 시 재계산될 슬라이드 너비변수

# 1.9.2. 작성

responseSlideWidth = slideWidth;
...
function responsiveSlide() {
	//반응형슬라이드
	$(window).resize(function () {
		let winWidth = $(this).width();
		if (winWidth < 900) {
			console.log(slides.width(), newSlideWidth);
			responsiveGap = 20;
			responseSlideWidth = (slides.width() - responsiveGap * (maxSlides - 1)) / maxSlides;
		} else {
			responseSlideWidth = slideWidth;
			responsiveGap = slideGap;
		}
		if (winWidth <= 500) {
			responseSlideWidth = slides.width();
			responsiveGap = 0;
		}
		slideLayout(responseSlideWidth, responsiveGap);
		setSlidePos();
	});
}

# 1.10. 디버깅

function moveSlideCb(n) {
	if (slides.is(':animated')) {
		return;
	}
	slides.stop().animate({ left: moveAmt * -n }, 500, function () {
		...
  1. $('el').is(조건) 요소가 조건과 일치하는지 검사하여 boolean 을 반환
  2. :animated 애니메이션 되고 있는 요소를 선택하는 jQuery 선택자