캐러셀에 스와이프 기능 만들기

조 은길·2022년 6월 7일
1

Html & CSS

목록 보기
64/66
post-thumbnail

구현할 기능

기능1.

내가 드레그한 거리만큼 사진도 왼쪽으로 움직임.
slide-container를 움직임 (카드 전체를 담고 있는 태그)

기능2.

드레그를 놓으면, 다음 사진이 보임.
=> 단, 일정 px이상 움직여야 되기에 이 점을 컨트롤 해줘야한다.
=> 일정 px 이하로 움직이면, 이미지 원상복귀!
(이때, transition을 줘서 자연스럽게 복귀할 수 있을 듯)

100px 이상 이동시, 다음 사진이 보임.
아니면, 다시 기존 사진이 보임.


기능 구현을 위해 알아야할 이벤트

  • mousedown : 마우스를 누를 때, 발생
  • mouseup : 마우스를 뗐을 때, 발생
  • mousemove : 집어넣은 태그에서 마우스를 움직일 때, 발동한다.

click 이벤트 = mousedown + mouseup

e.clientX => 현재 마우스위치의 X좌표
e.clientY 는 Y좌표이지만, 현재 문제 해결을 위해서는 X좌표만으로 충분!!


마우스 50px 움직였으면, slide-container도 50px만큼 움직여줘야 한다.

마우스를 찍고, 왼쪽으로 드레그 했으면, 위와 같은 길이가 나온다.
이 길이를 구하고 싶으면, 코드를 어떻게 짜야할까??

당연히 point 1 - point 2 이다.


이미지를 drag할 때, 아래와 같은 표시가 뜨는 이유

html의 요소들은 잡아서 끌 수가 있다. 즉, 잡아서 끌어서 어디다 갖다놓을 수가 있다.
=> 이것을 "drag 이벤트"라고 한다.

이 이벤트가 발동되는게 싫다면, img를 찾아서 해당 태그 안에 draggable = false를 넣어주자!!
=> 이러면 드레그&이동 안됨!!


기능 구현시, 발생한 에러들

  1. 길이 구하기
    마우스를 찍고, 왼쪽으로 드레그가 됐다가 마우스업이 발생하면, 그것이 최종 길이가 되야한다.
    즉, 마우스다운의 e.clientX 지점을 시작으로 마우스무브의 e.clientX가 마지막으로 잡아낸 지점의 차이가 최종 길이가 된다.
    문제는 e.clientX가 각각의 이벤트리스너 함수에만 존재해서, 전역 변수 start하나를 만들어서 할당해준 뒤에야 다른 이벤트리스너 함수에서도 사용할 수 있었다.

  2. 현재 마우스를 클릭한 상태가 아닌데도, img가 움직이는 문제
    mouseup 이벤트를 추가해서 해당 이벤트 발생시, isBegin=false;로 변경해주면서, 이미지의 움직임을 멈출 수있었다.
    isBegin 역시 전역변수로 현재 클릭이 되고, 드레그 되는지 안 되는지를 판단해주기 위해 존재하는 boolean값이다.

  3. 마우스 다운시, 특정 위치로 이동하는 문제

    첫번쨰 이미지 일때는 에러가 없는데,
    두번째 이미지를 "마우스 다운" 했을 때, 첫번째 이미지의 특정 위치로 이동한다.
    mousedown 이슈 같아서, 코드를 봐도 잘 모르겠다.

  • 해결법
    slideContainer.style.transform = translateX(${e.clientX - begin}px);`
    이 코드가 첫번째 이미지에서는 문제가 없지만, 2번째 이미지에서는 전체 면적을 한 번 더 더해줘야 한다.
.slide-box img {
        width: 1000px;
        height: 500px;
      }
width값이 1000px이므로 2번째 img 상에서 클릭시에는
begin = e.clientX + 1000; 해줘야, 2번째 이미지에서 클릭된 위치가 제대로 찍힌다.

마우스 vs 터치

본인이 구현한 사이트를 모바일 상에서 테스트 해보고 싶다면, devtool을 열고 모바일 환경으로 변경하면 된다.

여기서는 "클릭"이 아니라 "터치"이다.

그래서, 마우스 버튼이 아니라, 큰 점으로 바뀐거다.

현재는 마우스에 대한 이벤트만 구현해놔서, 모바일 환경에서는 전혀 작동하지 않는다.


터치 이벤트

touchstart (터치시작시 발동)

touchmove (터치중일 때 계속 발동)

touchend (터치종료시 발동)

이런 이벤트를 듣는 리스너를 부착하면 이제 터치스와이프 가능!


<script>
  $('.slide-box').eq(0).on('touchstart', function(){
    시작좌표 = e.touches[0].clientX;
    생략
  })

  $('.slide-box').eq(0).on('touchmove', function(){
    생략
  })

  $('.slide-box').eq(0).on('touchend', function(){
    생략
  })

</script>

기존 코드를 이렇게 바꾸면 됩니다.

터치 이벤트 주의사항

그럼 모바일에서도 아까랑 똑같이 동작하는데 주의사항은

e.clientX를 e.touches[0].clientX 이걸로 바꾸면 됩니다.

왜냐면 터치는 여러 손가락으로 할 수 있어서 그 중 몇번째 손가락인지 지정해줘야합니다.
touches[0]는 "첫번째 손가락"이라는 의미이다.

touchend는 touchstart와 touchmove랑은 좀 다르다

touchend 이벤트리스너에선 e.clientX 말고 e.changedTouches[0].clientX 쓰면 됩니다.


결론

마우스 이벤트 3개에 터치 이벤트 3개 총 6개의 유사한 이벤트리스너가 달린다.

근데, 이렇게 코드 짜는게 좀 긴 것같다.

그럴 때, 라이브러리의 도움을 받을 수있다.

Hammer.js

=> 터치와 클릭을 동시에 구현할 수 있게 해준다.
=> 브라우저 호환성도 잡아준다.


새로운 문제를 봤을 때,

  • 한글로 기능 설명부터 하고,

  • 작은 기능부터 만들어간다.


해당 github 링크

완벽한 캐러셀을 위해서는 추가적으로 구현해야할 기능들이 많은데, 나중에 시간적 여유가 되면, 완성해보겠다.

profile
좋은 길로만 가는 "조은길"입니다😁

0개의 댓글