본문 바로가기
Js&React 실습/JSprac

[JS]이미지 슬라이더 만들기(캐러셀)+추가

by sweesweet 2022. 6. 30.

https://sweesweett.github.io/jsprac/imgslider.html

이미지 슬라이더 프리뷰!

 

 

 

이미지슬라이더를 한번 구현해보고싶어서 며칠을 고민해서 만들었다. 잘 만들어진 슬라이더인지는 모르겠지만... 자신감은 없지만, 자신감 없다고 안쓰고 그냥 저기 구석에 던진다면 발전이 없을것 같아서... 미래의 똑똑한 내가 맘에 안들면 고치겠지^^ 란 생각으로 던진다.

+요즘에 너무 바빠서(복습에 치이고있음) 이걸 작성할 시간도 없지만 미래의 나를 위해서 정리

 

구글에 치면 자바스크립트로 이미지슬라이더(캐러셀)를 만든건 많이 봤지만, 다들  현재 사진만 나오고 다른 사진은 나오지 않는 스타일이었다(이것도 다른 페이지에 구현해볼 예정!). 내가 만들고자 했던 슬라이더는 사진과 같이 옆에 그 전 혹은 그 후의 사진들이 나오길 바랬다.

문제는 어떻게 구현하냐인데, 이것도 완벽한 구현은 아니라고 생각한다. 아래 동그라미 버튼을 클릭할때는 transition 효과를 없애야 예쁘게 보일 것 같다.

구현과정에서 가장 신경 쓴건 아래와 같다!

앞뒤로 그 전, 후 사진 나오게 하기
무한 뱅글뱅글 돌게 하기
버튼을 움직일때 뭔가 효과가 있기(?)

1. 앞뒤로 그 전, 후 사진 나오게 하기!

이부분에 대해서 정말 많은 고민을 했다. 위의  현재사진 나오는 부분에서 가로길이를 살짝넓혀서 끄트머리만 보이게할까
?그럼 어떻게 맨앞과 맨뒤를 연결할까 이런고민을 했는데 사실상, 보이는 부분을 움직여야 할 때(overflow:hidden), 구현을 고민하던 당시에는 다 absolute를 걸어놓은 탓에 아주 제멋대로 움직여서 포기한 감도 없지않아 있다( 그래서 다시 구현해본다는 말이었다. )

그렇다면 따로 맨 앞에 나올 사진을 class이름을 부여해서 css를 적용받게하는건 어떨까? 란 생각이 들었다. 그래서 active라는 class를 따로 줘서 버튼을 누를때 마다 그 다음 혹은 그전의 이미지가 가운데에 위치하게 됐다.

여기까진 아주좋았다. 차례대로 이미지는 순서에 맞게 잘 움직였다. 문제는 그 양옆에 사진들이 아주 랜덤하게(?) 순서없이 제멋대로 움직인다는 것이었다. 그래서 어쩔 수 없이 prev 와 next라는 class를 부여하고 해당하지 않는 이미지는 display:none을 줬다.

 

HTML

     <div class="img__wrapper">
        <img class="img1 active" src="./img/slider/haechi_01.png" alt="" />
        <img class="img2 next" src="./img/slider/haechi_02.png" alt="" />
        <img class="img3" src="./img/slider/haechi_03.png" alt="" />
        <img class="img4 prev" src="./img/slider/haechi_04.png" alt="" />
      </div>

JS

function moveTo() {
  document.querySelector('.colored').classList.remove('colored');
  document.querySelector('.prev').classList.remove('prev');
  document.querySelector('.next').classList.remove('next');
  document.querySelector('.active').classList.remove('active');
  document.querySelector(`.img${num}`).classList.add('active');// 2.뱅글뱅글과 관련있음
  document.querySelector(`.circle${num}`).classList.add('colored');//2.뱅글뱅글과 관련있음
  if (num === imgWrapper.children.length) {
    imgWrapper.firstElementChild.classList.add('next');
    document
      .querySelector('.active')
      .previousElementSibling.classList.add('prev');
  } else if (num === 1) {
    imgWrapper.lastElementChild.classList.add('prev');
    document.querySelector('.active').nextElementSibling.classList.add('next');
  } else {
    document.querySelector('.active').nextElementSibling.classList.add('next');
    document
      .querySelector('.active')
      .previousElementSibling.classList.add('prev');
  }
}

음 약간 코드가 아주 querySelector 남발인데 이게 이유가있다. 지정 후 다음 버튼을 눌렀을 때, undefined오류가 발생하기때문에 작동에 문제가있었다. 이 코드는 다시 생각해서 추후에..시간이있다면 수정해볼 예정이다..

이 코드를 짜면서 배운 게 있다면, Node.nextSibling은 nextSibling의 text만 갖고오는 것이고, Read Only라는 점이다.

어떤노드의 형제 노드를 가지고 오고싶다면 (previous/next)ElementSibling 을 사용하면된다.

만약 nextElementSibling을 사용하지않는다면 이미 조건에 나눠놨기때문에

 document.querySelector(`.img${num}`)

를 사용하면 되지 않을까 싶다! 

 

2. 무한 뱅글 뱅글 돌게 하기

위의 코드를 보다시피 숫자를 사용해서 돌게 하고 있다. 

처음에 어떻게 돌릴까 해서 숫자로 돌리자 싶어서, img class명에 숫자를 추가했었다.

우선 버튼을 누르면 숫자가 변경되고, 처음일 때와 마지막일 때의 조건을 넣어서 딱 .imgWrapper안에 들어있는 사진의 길이만큼까지만 돌게 했다. 이부분은 그렇게 어렵지 않았다. 그냥 내코드가 과연 효율적인 코드인건지 의심만 될 뿐ㅎㅎ

plusMinus();
function plusMinus() {
  document.querySelector('#prevBtn').onclick = () => {
    if (num === 1) {
      num = imgWrapper.children.length;
    } else num--;
    moveTo();
  };
  document.querySelector('#nextBtn').onclick = () => {
    if (num === imgWrapper.children.length) {
      num = 1;
    } else num++;
    moveTo();
  };
}

지금 생각해보면 굳이 플러스 마이너스 이벤트함수를 함수안에 왜 또 넣었는지 모르겠다. 이거 쓰고 다 수정해야겠다.

3.버튼을 움직일 때 뭔가 효과가 있기(?)

아직 애니메이션을 잘 알지 못하기에 transition을 통해 애니메이션 효과를 주기로했다.

여기서 주의할 점은 absolute를 했을 때 반드시 top, left를 쓸것인지 bottom,left등등 을 쓸것인지 다 맞춰야한다.

아니면 누를때마다 떡먹는 용만이처럼 튀어나가는 사진들을 볼 수 있음..

나는 이미지에 transition: all ease-out 0.7s; 을 주었다

 

4.동그라미를 클릭하면 해당슬라이드로 이동

이건 마지막에 추가로 구현한 부분인데, 이미지와 똑같이 동그라미에 숫자를 클래스로 부여하고 눌렀을 때  해당 이미지로 이동하게끔 만들었다.

HTML

<div class="sliderCircle">
        <div class="circle circle1 colored"></div>
        <div class="circle circle2"></div>
        <div class="circle circle3"></div>
        <div class="circle circle4"></div>
      </div>

JS

function navigateImg(e) {
  if (e.target.classList.contains('circle')) {
    const className = e.target.classList[1];
    num = Number(className[className.length - 1]);
    moveTo();
  } else {
    return;
  }
}

 

아쉬운점있다면 동그라미 버튼을 눌렀을 때 다음페이지로 넘어갈땐 멀쩡한데 1에서 3페이지로 넘어갈때는 양옆의 사진들이 그냥 자리만바꾼다. 이부분은  꼭 고칠것이다... 동그라미로 이동할때는 transition을 없애는걸로~

 

+220703

아쉬운 점을 고치긴 했다. 다만 이렇게 비효율적으로 해야하는건지뭔지.. 그리고 다시 앞뒤 버튼을 눌렀을 때 같은 방법으로 transition값을 주었다..

function navigateImg(e) {
  if (e.target.classList.contains('circle')) {
    const className = e.target.classList[1];
    num = Number(className[className.length - 1]);
    document
      .querySelectorAll('img')
      .forEach((el) => (el.style.transition = 'unset'));//<-이부분 추가
    moveTo();
  } else {
    return;
  }
}

+220711

오늘 웹 접근성에 대해 배웠는데
자동 변경 슬라이드 (캐러셀 슬라이드) : 이전, 다음, 정지 기능을 제공해야 하며, 정지 버튼이 없더라도 마우스 호버 혹은 키보드 접근시에 정지되도록 구현해야 함

라고해서 그냥 자동으로 돌게만 만들어놨는데 다시 수정했다.

정지 버튼이 없더라도 마우스 호버 혹은 키보드 접근시에 정지되도록 구현해야 함<- 이부분은 이해가 안가서..포기하구 

동그라미들을 누르면 자동으로 도는게 멈추고, 다시 플레이버튼을 눌러야지 자동 회전(?)이 되게 만들었다.

 

이전에 가위바위보를 통해서 배웠던 setInterval  다시돌게하는 방법을 통해 플레이버튼과 일시정지 버튼이 잘 작동하도록 만들었다

function startInterval() {
  nextInterval = setInterval(toNext, 2000);
}
function stopInterval() {
  clearInterval(nextInterval);
}
document.getElementById('play').onclick = startInterval;// 위의 next버튼 이벤트에 걸려있던 콜백함수를 따로 함수로 만들음
document.getElementById('pause').onclick = stopInterval;