[javascript] 무한 롤링 이미지 배너 구현 - 2. 앞뒤 이동 버튼 구현
한 방향으로만 무한 롤링되는 배너에 양방향 이동 화살표를 추가해 사용자 조작으로 배너를 돌려볼 수 있도록 기능을 개선해 보겠습니다.
먼저 이동 화살표 이미지는 폰트어썸(FontAwesome) 오픈소스 벡터 아이콘 이미지를 가져와 사용합니다.
HTML 페이지 헤더 영역에 폰트어썸 아이콘 CSS 링크를 추가합니다.
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" crossorigin="anonymous">
이전, 다음 화살표 아이콘을 롤링 이미지들 앞쪽에 추가합니다.
<div class="img_wrap">
<div class="prev btnmove">
<a href="#" title="이전"><i class="fas fa-chevron-left"></i></a>
</div>
<div class="next btnmove">
<a href="#" title="다음"><i class="fas fa-chevron-right"></i></a>
</div>
<ul class="rollimgs">
<li><img src="./backup/707/img/banner1.jpg"></img></li>
<li><img src="./backup/707/img/banner2.jpg"></img></li>
<li><img src="./backup/707/img/banner3.jpg"></img></li>
</ul>
</div>
위치를 잡기 위해 화살표 아이콘 위치를 CSS로 지정해줍니다.
CSS가 적용되면 반투명한 화살표 2개가 롤링 이미지 좌우의 고정된 위치에 배치되어 보입니다.
.img_wrap .btnmove{
position: absolute;
top: 268px;
width: 40px;
height: 85px;
z-index: 1;
font-size: 4em;
opacity: 0.5;
}
.img_wrap .btnmove.prev{
left: 10px;
}
.img_wrap .btnmove.next{
right: 10px;
}
.img_wrap i{
color: #fff;
}
초기화 이벤트 리스너에 화살표 클릭 이벤트 리스너를 추가합니다.
좌우 버튼을 눌렀을 때 어느 버튼이 눌렸는지 클래스로 구분해서 오른쪽으로 롤링할지, 왼쪽으로 롤링할지를 결정합니다.
//앞뒤 클릭 이벤트 리스너
document.querySelectorAll('.btnmove').forEach(function(item){
item.addEventListener('click', function(e){
clearInterval(banner.rollId);//롤링 인터벌 해제
//화살표 방향 구분
if(e.target.parentElement.parentElement.classList.contains('prev')){
banner.rollPrev();
}else{
banner.rollNext();
}
banner.rollId = setInterval(banner.rollNext, banner.interval);//롤링 인터벌 재호출
});
});
"prev" 클래스가 있으면(e.target.parentElement.parentElement.classList.contains('prev')) 왼쪽 배너로, 없으면 오른쪽 배너로 이동합니다.
이벤트 처리 앞뒤를 보면 앞에는 타이머 객체를 해제하고, 롤링 메서드 호출 후에 타이머 객체를 다시 생성하는 것을 볼 수 있습니다.
이것은 타이머가 돌고 있는 중일 경우 이벤트 클릭과 중복으로 실행되어, 배너가 2개가 한꺼번에 이동하거나, 이동하다 되돌아오는 충돌현상을 막기 위한 것입니다.
사용자 클릭에 의한 롤링이 호출된 후 타이머를 다시 시작해 사용자 액션과 타이머 액션이 중복되지 않도록 하기 위한 고급 기법입니다.
오른쪽 방향으로 롤링하는 메서드(rollNext)는 이미 구현되어 있으므로, 왼쪽 방향으로 롤링하는 메서드를 추가로 구현해서 객체 리터럴에 추가합니다.
//이전 배너 롤링
rollPrev: function () {
document.querySelector('.rollimgs').classList.add('reverse');
if(document.querySelector('.nextroll')){
document.querySelector('.nextroll').classList.remove('nextroll');
}
if(document.querySelector('.currentroll')){
document.querySelector('.currentroll').classList.add('nextroll');
document.querySelector('.currentroll').classList.remove('currentroll');
}
if(document.querySelector('.prevroll')){
document.querySelector('.prevroll').classList.add('currentroll');
document.querySelector('.prevroll').classList.remove('prevroll');
}
if(document.querySelector('.currentroll').previousElementSibling){
document.querySelector('.currentroll').previousElementSibling.classList.add
('prevroll');
}else{
document.querySelector('.rollimgs li:last-child').classList.add('prevroll');
}
}
이제 화살표 버튼을 클릭하면 원하는 방향으로 배너를 돌려가면서 볼 수 있습니다.
화살표 클릭이 더 이상 없으면, 지정된 시간 간격으로 다시 오른쪽 방향으로 배너가 무한 롤링됩니다.
배너를 반대 방향으로 무한 롤링 하려면
초기화 이벤트 리스너와, 객체 리터럴의 초기화 메서드(rollInit) 에서 호출하는 타이머 함수의 "rollNext" 를 "rollPrev" 로 변경해주면 됩니다.
this.rollId = setInterval(this.rollPrev, this.interval);//롤링 인터벌 호출