JS 로 css transition 구현하기

강정우·2023년 5월 12일
0

JavaScript

목록 보기
39/53
post-thumbnail

Vanilla JS

<!DOCTYPE html>
<html>
<head>
  <style>
    .transition-element {
      width: 200px;
      height: 200px;
      background-color: red;
      position: relative;
    }
  </style>
</head>
<body>
  <div class="transition-element"></div>

  <script>
    const element = document.querySelector('.transition-element');

    // 클릭 이벤트 처리
    element.addEventListener('click', function() {
      const startPosition = parseInt(getComputedStyle(element).left);
      const targetPosition = startPosition + 100; // 목표 위치
      const duration = 1000; // 전환 시간 (1초)
      const interval = 10; // 이동 간격 (ms)

      let currentTime = 0;

      function move() {
        currentTime += interval;

        const progress = Math.min(currentTime / duration, 1); // 진행 상태 (0~1)

        const currentPosition = startPosition + (targetPosition - startPosition) * progress;
        element.style.left = currentPosition + 'px';

        if (progress < 1) {
          setTimeout(move, interval);
        }
      }

      move();
    });
  </script>
</body>
</html>
  • 위 코드에서는 클릭 이벤트가 발생하면 move 함수가 호출되며, setTimeout을 사용하여 일정한 간격(interval)으로 요소를 이동시킨다.
    시작 위치(startPosition)에서 목표 위치(targetPosition)까지의 이동 거리를 1초 동안 부드럽게 이동하는 코드이다.

주의

  • 요소가 이동하기 위해서는 position: relative; 속성이 필요하다.
    위 코드에서는 이동을 위해 left 속성을 사용하였다. 요소의 초기 위치가 왼쪽에서부터 이동할 거리보다 멀리 떨어져 있을 경우, 시작 위치(startPosition)를 조정해야 할 수도 있다.

  • 아래 예제 코드는 주의 사항을 적용하여 Vue.js를 이용하려 작성한 예제코드이다.

  • 바로 앞서 포스팅한 Font-awesome 태그와 함께 작성되었다.

mark-up 컴포넌트

<font-awesome-icon :icon="['fas', 'arrow-left']" class="arrowIcon" @click="goScroll('L')"/>
<div class="boardMenu"
     ref="scrollable" @mousedown="onMouseDown" @mousemove="onMouseMove" @mouseup="onMouseUp"
     >
  <div v-for="board in getBoardCtgry" :key="board.boardSeq">
    <router-link :to="{ path: '/onpoom/board', query: { seq: board.boardSeq } }">
      <div class="boardTab" @click="handleTabClick(board.boardSeq)" :class="{ sel: selectedTab === board.boardSeq }">
        {{board.boardName}}
      </div>
    </router-link>
  </div>
</div>
<font-awesome-icon :icon="['fas', 'arrow-right']" class="arrowIcon" @click="goScroll('R')"/>
  • 위 코드는 상단의 메뉴 tab에서 보이는 컴포넌트를 작성한 것이다. 각각이 router-link로 만들어져 있으며 query string으로 값을 가져와서 각각의 sel 태그를 활성화하였다.

  • 사실 nested route를 쓰면 편하지만 이미 왼쪽 메뉴바를 구현해봐서 query-string을 이용하여 위 tab화면을 구현해보고 싶었다.

goScroll(direction) {
  const startPosition = this.$refs.scrollable.offsetLeft/3;
  const targetPosition = startPosition + 10; // 목표 위치
  const duration = 500;
  const interval = 10; // 이동 간격 (ms)
  let currentTime = 0;
  const move = () => {
    currentTime += interval;
    const progress = Math.min(currentTime / duration, 1); // 진행 상태 (0~1)
    const currentPosition = startPosition + (targetPosition - startPosition) * progress;
    if(direction==='L'){
      this.$refs.scrollable.scrollLeft -= currentPosition;
    }else{
      this.$refs.scrollable.scrollLeft += currentPosition;
    }
    if (progress < 1) {
      setTimeout(move, interval);
    }
  }
  move();
},
  • mouse로 가로스크롤구현하는 코드를 보고싶다면 다음 포스팅을 참조하면 된다.

  • 무큰 위 코드는 3번의 클릭으로 끝까지 naviage를 할 수 있는 코드이다.

  • 참고로 this.$refs.scrollable.offsetLeft는 위 사진의 주황색 선을 나타낸다.

  • startPosition 변수는 스크롤 가능한 요소의 현재 가로 스크롤 위치를 나타내고 offsetLeft 속성을 사용하여 요소의 가로 스크롤 위치를 구한다.

  • targetPosition 변수는 목표로 하는 가로 스크롤 위치를 나타낸다. 현재 위치에서 10만큼 이동하는 것을 목표로 설정한다.
    이 값을 조정하여 이동 거리를 변경할 수 있다.

  • duration 변수는 애니메이션의 전체 시간을 나타낸다.

  • interval 변수는 이동 간격을 나타낸다. 10ms로 설정하여 0.01초마다 이동하도록 구현하였다.

  • currentTime 변수는 애니메이션의 현재 진행 시간을 나타낸다.

  • 마지막으로 move 함수는 애니메이션을 실제로 실행하는 함수이다. currentTime 값을 업데이트하고 진행 상태를 계산하여 현재 위치를 결정한다.
    이후 스크롤 가능한 요소의 scrollLeft 속성을 업데이트하여 스크롤을 이동한다.

  • 진행 상태가 1보다 작을 경우 재귀적으로 move 함수를 계속 호출하여 애니메이션을 진행해 나간다.

profile
智(지)! 德(덕)! 體(체)!

0개의 댓글