무한 이미지 슬라이드
개요
웹 사이트를 돌아다니다보면 광고 이미지가 한장 한장씩 일정 시간동안 보여지고 오른쪽으로 넘어가길 무한번 반복하는 것을 볼 수 있다.
어떻게 구현하는걸까?
원리
우선 이미지 슬라이드의 기본 원리는 이렇다.
이미지가 보일 공간을 만들고 바깥으로 빠져나오는 요소는 보이지 않게 한다.
overflow : hidden;
을 사용하면 된다. 그러나 직접 보면서 작성하기 위해 일단은 사용하지 않은 모습이다.
그리고 요소들을 이어붙여서 마치 영화 필름과 같이 만든다.
그리곤 overflow : hidden;
을 적용하면 삐져나오는 요소들이 보이지않게된다.
그 다음엔 JS를 이용하여 조작해주면 된다.
이미지가 움직이는 것처럼 보이려면 ul을 div의 너비만큼 왼쪽으로 이동시키면 된다.
요소 자기 자신이 원래 정해진 위치에서 움직여야한다. -> 포지션 릴레이티브!
일단 시간을 지정하고 사용하지 않고 버튼을 누를시 작동하게 만들자면 이렇다.
overflow : hidden을 적용한 모습.
애니메이션 적용
일정 시간 간격으로 정해둔 로직을 실행시키는 함수는 setInterval
이 있다.
이를 이용해 애니메이션을 설정해본다면 이렇다.
<script>
startSlide();
function startSlide() {
let count = 1
setInterval(function(){
const ul = document.querySelector('ul');
ul.style.transition = '0.4s';
ul.style.right = 100 * count + "px";
count++;
if(count === 3) {
count = 0;
}
},1000);
}
</script>
이렇게 무한 슬라이드가 구현되었다.
전체 소스코드
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style>
div {
width : 100px;
height : 100px;
border : 1px solid black;
overflow : hidden;
margin : 0px auto;
}
ul {
position: relative;
width : 300px;
display : flex;
padding : 0px;
margin : 0px;
}
li {
width : 100px;
height : 100px;
background-color: #ddd;
list-style : none;
border : 1px solid black;
line-height : 100px;
text-align : center;
}
</style>
</head>
<body>
<div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
<script>
startSlide();
function startSlide() {
let count = 1
setInterval(function(){
const ul = document.querySelector('ul');
ul.style.transition = '0.4s';
ul.style.right = 100 * count + "px";
count++;
if(count === 3) {
count = 0;
}
},1000);
}
</script>
</body>
</html>
세상은 거짓말 투성이야
위의 방식처럼 애니메이션을 적용해보면 문제없이 작동한다.
그러나 살짝 아쉬운 부분이 있는데 바로 슬라이드의 맨 마지막에서 제일 처음의 슬라이드로 넘어갈 때 다소 부자연스러운 동작이 나온다는 것이다.
동작의 순서를 보면 1 -> 2 -> 3 -> 2 -> 1의 순서로 넘어간다.
3 -> 2 -> 1은 원래 1초에 한 슬라이드씩(+100px) 넘어가 right값이 300px인 것이 짧은 시간에 0px로 바뀌니 후다닥 넘어간다.
이를 자연스럽게 만들기위해 일종의 트릭을 이용해야한다.
일단 제일 처음의 슬라이드를 복사한뒤 맨 마지막 슬라이드 다음에 붙여넣는다.
그러면 1 -> 2 -> 3 -> 1 의 흐름이 만들어진다.
그런 다음 setTimeout을 이용하여 0.41s후 0.4s로 설정되어있는 transition을 0s로 만들고 위치를 제일 첫번째 슬라이드로 바꾼다.
즉, transition의 효과가 끝나고 마지막 슬라이드에 이어붙인 첫번째 슬라이드가 자리잡은 뒤 0.01초 후 transition을 끄고 제일 처음 슬라이드로 이동시키는 트릭을 사용할 수 있다.
그럼 transition이 사라진 상태에서 제일 처음의 슬라이드로 이동하기 때문에 1 -> 2 -> 3 -> 1로 왔을 때 애니메이션 효과가 사라지고 제일 처음의 슬라이드를 보여줌으로써 유저의 입장에서는 다음과 같이 보이게 된다.
1 -> 2 -> 3 -> 1 -> 2 -> 3 -> …. 무한 반복
이런 방법으로 자연스러운 무한 슬라이드를 구현할 수 있다.
최종 코드
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style>
div {
width : 100px;
height : 100px;
border : 1px solid black;
margin : 0px auto;
overflow : hidden;
}
ul {
position: relative;
width : 400px;
display : flex;
padding : 0px;
margin : 0px;
}
li {
width : 100px;
height : 100px;
background-color: #ddd;
list-style : none;
border : 1px solid black;
line-height : 100px;
text-align : center;
}
</style>
</head>
<body>
<div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
<script>
startSlide();
function startSlide() {
let count = 1
const ul = document.querySelector('ul');
let firstEl = ul.firstElementChild.cloneNode(true);
ul.appendChild(firstEl);
setInterval(function(){
ul.style.transition = '.4s';
ul.style.right = 100 * count + "px";
count++;
if(count === 4) {
setTimeout(function() {
ul.style.transition = '.0s';
ul.style.right = "0px"
}, 401);
count = 1;
}
}, 1000);
}
</script>
</body>
</html>