whatisthis?

practice - js ) 슬라이드 페이지 (2) 터치형(드래그) 본문

PRACTICE/SELF

practice - js ) 슬라이드 페이지 (2) 터치형(드래그)

thisisyjin 2022. 3. 11. 15:49

슬라이드 페이지  

 (2) 터치형(드래그)

 

 

 

- 📃 실습하면서 알게된 점 기록

📌touch 이벤트


changedTouches

The TouchEvent.changedTouches property is a TouchList object that contains one Touch object for each touch point which contributed to the event.

>> 즉, touchList 객체이므로 첫번째 아이템인 [0]을 가져온것.
(터치가 여러군데 되면 여러 값 존재)


+) 그 외에도 
TouchEvent.targetTouches
TouchEvent.touches
등의 프로퍼티가 존재함.

++) 터치 이벤트에는 (event)
touchstart, touchmove, touchend, touchcancel이 존재.

https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/changedTouches

 

TouchEvent.changedTouches - Web APIs | MDN

The changedTouches read-only property is a TouchList whose touch points (Touch objects) varies depending on the event type, as follows:

developer.mozilla.org

 

 

index.html (style 내장)

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Slide Banner</title>
    <style>
      * {
        box-sizing: border-box;
      }

      /* 드래그 방지 */
      body {
        -ms-user-select: none;
        -moz-user-select: none;
        -webkit-user-select: none;
        -khtml-user-select: none;
        user-select: none;
      }

      .outer {
        border: 6px solid #525252;
        width: 300px;
        height: 200px;
        margin: 0 auto;
        overflow-x: hidden;
      }

      .inner-grp {
        display: flex;
        transition: all 0.3s ease-out;
        height: 100%;
      }

      .inner {
        padding: 0 16px;
        color: #fff;
        text-align: center;
      }

      .inner:nth-of-type(1) {
        background-color: rgb(209, 0, 0);
      }
      .inner:nth-of-type(2) {
        background-color: rgb(255, 248, 49);
      }
      .inner:nth-of-type(3) {
        background-color: rgb(60, 0, 255);
      }
    </style>
  </head>
  <body>
    <div class="outer">
      <div class="inner-grp">
        <div class="inner">
          <h2>First</h2>
        </div>
        <div class="inner">
          <h2>Second</h2>
        </div>
        <div class="inner">
          <h2>Third</h2>
        </div>
      </div>
    </div>
    <script src="app.js"></script>
  </body>
</html>

 

app.js

// Div 사이즈 js로 조절하기

const outer = document.querySelector(".outer");
const innerGrp = document.querySelector(".inner-grp");
const inners = document.querySelectorAll(".inner");

let currentIndex = 0;
let currentTransition;

inners.forEach(inner => {
  inner.style.width = `${outer.clientWidth}px`;
  console.log(outer.clientWidth);
});

innerGrp.style.width = `${outer.clientWidth * inners.length}px`;

// Event Listener

let isSlide = false;
let slideStartX = 0;
let slideGab = 0;
const flipGab = 80;
// 🔺 gab이 80이상이여야 넘어가게


// 📌 slide시작시 - transition 저장해놓고 잠시 삭제함 (느려지니까)

const slideStart = clientX => {
  slideStartX = clientX;
  isSlide = true;

  currentTransition = window.getComputedStyle(innerGrp).transition;

  innerGrp.style.transition = "initial";
};


// 📌 slide 하는동안(마우스 누르는동안) - gab에 따라서 margin-left 달라지게

const slideMove = clientX => {
  if (isSlide) {
    slideGab = slideStartX - clientX;
    if (currentIndex >= inners.length - 1 && slideGab > 0) {
      slideGab = 0;
      // 마지막슬라이드에서는 gab을 0으로 설정
    }
    // 🔻 margin-left 줌 (gab에 따라서 달라지게)
    innerGrp.style.marginLeft = `-${
      outer.clientWidth * currentIndex + slideGab
    }px`;
  }
};


// 📌 slide 끝 (마우스 뗌) - 좌우 드래그 판단후 인덱스 올리기 + margin-left주기

const slideEnd = () => {

// slidegab이 80보다 클때 - 우로 드래그함 (인덱스 증가) 
  if (slideGab >= flipGab) {
    currentIndex++;
    currentIndex =
      currentIndex >= inners.length ? inners.length - 1 : currentIndex;
  } else if (slideGab <= -flipGab) {
  // slidegab이 -80보다 작음 - 좌로 드래그함 (인덱스 감소)
    currentIndex--;
    currentIndex = currentIndex < 0 ? 0 : currentIndex;
  }
  // margin-left 줌
  innerGrp.style.marginLeft = `-${outer.clientWidth * currentIndex}px`;
  // 변수들 초기화 
  slideGab = 0;
  isSlide = false;
  // 트랜지션도 초기화 (다시 적용)
  innerGrp.style.transition = currentTransition;
};

// 데스크탑 전용

innerGrp.addEventListener("mousedown", e => {
  slideStart(e.clientX);
});
innerGrp.addEventListener("mousemove", e => {
  slideMove(e.clientX);
});
innerGrp.addEventListener("mouseup", e => {
  slideEnd();
});

// 터치 - 모바일 전용

innerGrp.addEventListener("touchstart", e => {
  slideStart(e.changedTouches[0].clientX);
});
innerGrp.addEventListener("touchmove", e => {
  slideMove(e.changedTouches[0].clientX);
});
innerGrp.addEventListener("touchend", e => {
  slideEnd();
});

 

 


 

result

 

 

 

 

사담 👻

 처음엔 왜 굳이 width를 js로 주지? 했는데
따지고보면 ...  나중에 페이지가 늘어나거나 하면 이게 더 확실하기도 하고,
DOM객체의 clientWidth를 받아오니까 하나가 변해도 계속 유지되고.. 등등 장점이 있다.
그래도 역시 js로 CSS 변경하는건 생소하긴 하네.
클래스 넣고빼고 하는 방법을 생각했는데 이보다 더 나은 방법은 못찾겠음.. 

암튼! js 재밌다.
(진짜임)