3 분 소요

**[공지사항]** [개인적인 공부를 위한 내용입니다. 오류가 있을 수 있습니다.]

[반응형 홈페이지 만들기-010]

Section 內 화살표 버튼 기능 구현 - 01

[버튼의 위치]



[화면 구성도]



[버튼의 동작 관련 순서도]



화살표에 마우스가 호버링 했을때 색상과 움직임을 표현하기 위해 style.css에 다음과 같이 작성한다.
  .slide-prev-hover:hover {
    transition: transform 0.5s;
    transform: translateX(-2px);
  }

  .slide-next-hover:hover {
    transition: transform 0.5s;
    transform: translateX(-2px);
  }


왼쪽 화살표에 click 이벤트가 발생했을때 왼쪽 화살표의 동작과 오른쪽 화살표는 어떻게 동작해야 하는지에 대해 아래와 같이 구현한다.
function transformPrev(event) {
    const slidePrev = event.target; // event.target의 의미는 하단 코드 中 eventListner가 동작하는 것을 의미
    // 아래 동작하는 event가 slidePrevList를 click하는 것이기에 그 event를 slidePrev로 상수를 선언함.
    const slideNext = slidePrev.nextElementSibling; 

    // ul 태그 선택
    const classList = slidePrev.parentElement.parentElement.nextElementSibling; //ul 태그 선택하여 선언
    let activeLi = classList.getAttribute('data-position');
    const liList = classList.getElementsByTagName('li'); //ul태그 내 li 태그 선택하여 선언

  /* classList.clientWidth 는 ul 태그의 실질적인 너비 ※ clientWidth는 js 내부용어
   * liList.length * 260 에서 260 은 각 li 요소의 실질 너비(margin 포함)
   * activeLi 는 data-position 에 있는 현재 위치 
   * 즉, liList.length * 260 + Number(activeLi) 는 현재 위치부터 오른쪽으로 나열되야 하는 나머지 카드들의 너비
   */

  /* classList.clientWidth < (liList.length * 260 + Number(activeLi)) 의미는
   * 오른쪽으로 나열될 카드들이 넘친 상태이므로, 왼쪽으로 이동이 가능함
   * Number(activeLi) : activeLi가 String 일 수 있기 때문에 숫자로 변환해 줌
   */

  if (classList.clientWidth < (liList.length * 260 + Number(activeLi))) {
    // 위치를 왼쪽으로 260 이동 (-260px)
    activeLi = Number(activeLi) - 260;

    /* 위치를 왼쪽으로 260 이동 (-260px)
    * 해당 위치는 변경된 activeLi 값이 적용된 liList.length * 260 + Number(activeLi) 값임
    * 이 값보다, classList.clientWidth (ul 태그의 너비)가 크다는 것은
    * 넘치는 li 가 없다는 뜻으로, NEXT 버튼은 활성화되면 안됨
    */
   if (classList.clientWidth > (liList.length * 260 + Number(activeLi))) {
     slidePrev.style.color = '#cfd8dc'; // 하늘색
     slidePrev.classList.remove('slide-prev-hover'); // 비활성화(클릭을 누른 경우 동작 필요 없음)
     slidePrev.removeEventListener('click', transformPrev);
   } 

    slideNext.style.color = '#2f3059'; // 남색
    slideNext.classList.add('slide-next-hover'); // 활성화
    slideNext.addEventListener('click', transformNext);
}

classList.style.transition = 'transform 1s';
classList.style.transform = 'translateX(' + String(activeLi) + 'px)';
classList.setAttribute('data-position', activeLi);
}


아래 이미지는 위의 자바스크립트 내용 중 classList, activeLi, liList만 선언한 상태에서
크롬의 개발자도구에서 breakpoint를 찍고 선언한 값들이 정상인지 아닌지를 확인해보는 것이다.


여기까지 작성 후 <- 버튼이 정상적으로 동작하고 활성화, 비활성화되는지를 확인한다.
-> 버튼에 대한 기능도 구현해준다.
function transformNext(event) {
    const slideNext = event.target;
    const slidePrev = slideNext.previousElementSibling;

    const classList = slideNext.parentElement.parentElement.nextElementSibling;
    let activeLi = classList.getAttribute('data-position');
    const liList = classList.getElementsByTagName('li');

    // 하나의 카드라도 왼쪽으로 이동했다면, 오른쪽으로 갈 수 있음
    if (Number(activeLi) < 0) {
        activeLi = Number(activeLi) + 260;

        // 왼쪽에 있던 카드가 오른쪽으로 갔다면, 다시 왼쪽으로 갈 수 있으므로 PREV 버튼 활성화
        slidePrev.style.color = '#2f3059'; 
        slidePrev.classList.add('slide-prev-hover'); // 호버링 시 반응 구현
        slidePrev.addEventListener('click', transformPrev); // 왼쪽 화살표 누르면 동작해야 함

        // 맨 왼쪽에 현재 보이는 카드가, 맨 첫번째 카드라면, 오른쪽 즉, NEXT 로 갈 수 없으므로 NEXT 버튼 비활성화
        if (Number(activeLi) === 0) {
            slideNext.style.color = '#cfd8dc';
            slideNext.classList.remove('slide-next-hover');  //호버링 시 무반응 구현
            slideNext.removeEventListener('click', transformNext); //오른쪽으로 갈 필요 없으니 동작X(remove)
        }
    }

    classList.style.transition = 'transform 1s';
    classList.style.transform = 'translateX(' + String(activeLi) + 'px)';
    classList.setAttribute('data-position', activeLi);    
}


여기까지 작성 후 화살표의 두 버튼이 정상적으로 동작하는지 확인한다.
1)초기값(활성화/비활성화)
2)호버링과 무빙액션
3)이동 후 버튼의 활성화 비활성화 여부
두 버튼의 동작이 순서도에 맞게 작동하는지 확인해본다.



좌우화살표 구현 관련 자바스크립트

/*----------------------------------------------------------------------*/
function transformNext(event) {
    const slideNext = event.target;
    const slidePrev = slideNext.previousElementSibling;
    const classList = slideNext.parentElement.parentElement.nextElementSibling;
    let activeLi = classList.getAttribute('data-position');
    const liList = classList.getElementsByTagName('li');
    if (Number(activeLi) < 0) {
        activeLi = Number(activeLi) + 260;
        slidePrev.style.color = '#2f3059';
        slidePrev.classList.add('slide-prev-hover');
        slidePrev.addEventListener('click', transformPrev);
        if (Number(activeLi) === 0) {
            slideNext.style.color = '#cfd8dc';
            slideNext.classList.remove('slide-next-hover');
            slideNext.removeEventListener('click', transformNext);
        }
    }

    classList.style.transition = 'transform 1s';
    classList.style.transform = 'translateX(' + String(activeLi) + 'px)';
    classList.setAttribute('data-position', activeLi);    
}

function transformPrev(event) {
    const slidePrev = event.target;
    const slideNext = slidePrev.nextElementSibling;
    const classList = slidePrev.parentElement.parentElement.nextElementSibling;
    let activeLi = classList.getAttribute('data-position');
    const liList = classList.getElementsByTagName('li');  
   if (classList.clientWidth < (liList.length * 260 + Number(activeLi))) {
       activeLi = Number(activeLi) - 260;
      if (classList.clientWidth > (liList.length * 260 + Number(activeLi))) {
        slidePrev.style.color = '#cfd8dc';
        slidePrev.classList.remove('slide-prev-hover');
        slidePrev.removeEventListener('click', transformPrev);
      } 
       slideNext.style.color = '#2f3059';
       slideNext.classList.add('slide-next-hover');
       slideNext.addEventListener('click', transformNext);
   }
   classList.style.transition = 'transform 1s';
   classList.style.transform = 'translateX(' + String(activeLi) + 'px)';
   classList.setAttribute('data-position', activeLi);
}

const slidePrevList = document.getElementsByClassName('slide-prev');

for (let i = 0; i < slidePrevList.length; i++) {
    let classList = slidePrevList[i].parentElement.parentElement.nextElementSibling;
    let liList = classList.getElementsByTagName('li');
    if (classList.clientWidth < (liList.length * 260)) {
        slidePrevList[i].classList.add('slide-prev-hover');
        slidePrevList[i].addEventListener('click', transformPrev);
    } else {
       const arrowContainer = slidePrevList[i].parentElement;
       arrowContainer.removeChild(slidePrevList[i].nextElementSibling);
       arrowContainer.removeChild(slidePrevList[i]);
    }
}

댓글남기기