텍스트 돌아가는 배너 만들기 (javascript)

외부 라이브러리

라이브러리는 Zepto와 anime.js를 이용했다.

Zepto는 편리하게 엘리먼트를 선택하기 위해서이고, anime.js는 편하게 loop를 설정하기 위하여 이용했다. css animation을 꼭 이용해보고 싶었지만, css에 변수를 어떻게 전달할지에 대한 마땅한 대책이 떠오르지 않아서 애니메이션 라이브러리를 이용했다.

아래 전체 코드에서 확인할 테지만, head 태그 부분에서 스크립트를 불러올 수 있도록 했다.


전체 코드

아래 Result를 눌러보면 바로 결과를 확인할 수 있다.


구현 흐름

  1. DOM을 관리할 수 있는 자바스크립트 라이브러리를 이용해 (여기서는 zepto이다.) 텍스트 및 데이터들을 불러온다.
  2. 텍스트를 실제로 화면에 띄운 다음에, 가로 사이즈를 측정한다.
  3. 배너 전체 너비가 다 채워질 때까지 텍스트를 복제한다. 정확히는 (배너 전체 너비 + 텍스트 하나의 너비)가 다 채워져야 한다. 왜냐하면 텍스트가 움직이는 만큼에도 텍스트가 채워져 있어야 하기 때문이다.
  4. 텍스트를 일정한 속도로 이동시키고, 이동된 x가 텍스트 너비만큼 이동되는 순간 0으로 초기화시킨다. 이를 무제한 반복한다. (실제로는 자바스크립트에서 매 렌더링 프레임마다 특정 코드를 실행시키는 것이 번거로워서 무한루프 기능이 있는 자바스크립트 애니메이션 라이브러리인 anime.js를 이용했다.)

실제 구현시 유의사항

Zepto(function($) {
  $(window).on('load', function() {
    $.each($(".ezkorry-roller"), function(index, item) {
      ...
    });
  })
});

배너에 돌릴 텍스트의 가로 사이즈를 구할 때, DOMContentLoaded 이벤트는 단순히 DOM 구조가 완료되었을 때 실행되므로, 실제 폰트가 아닌 기본 폰트로 적용된 상태에서 가로 길이를 구하기 때문에 우리의 의도에 살짝 빗나간다. 실제 폰트가 적용되었을 때 가로 길이를 구할 수 있도록 load 이벤트를 이용한다.


.ezkorry-roller {
  overflow: hidden;
  white-space: nowrap;
}

가장 바깥 쪽 div 요소 (위 예제에서는 .ezkorry-roller)의 내용에 대해 스크롤이 생기지 않도록 overflow: hidden; white-space: nowrap; 의 내용으로 css를 적용해주었다.


      const wrapper = $("<div />", { class:"ezkorry-roller-wrapper"});
      const roller = $(item);
      roller.append(wrapper);
      const span = roller.find('span').first();
      wrapper.append(span);

실제 텍스트인 spandiv.ezkorry-roller 사이에 div.ezkorry-roller-wrapper를 놓은 이유는, 이 요소에다가 움직이는 애니메이션을 먹일 것이기 때문이다. 기존의 구조에서는 애니메이션을 먹일 요소가 마땅히 없다.


      const span_width = span.get(0).offsetWidth;
      const max_width = roller.width() + span_width;
      let inner_width = span_width;

      while(max_width > inner_width) {
        wrapper.append(span.clone());
        inner_width += span_width;
      }
      
      anime({
        targets: '.ezkorry-roller-wrapper',
        translateX: {
          value: '-=' + span_width + 'px',
          duration: 3000
        },
        loop: true,
        easing: 'linear'
      });

핵심 부분이다. span_width는 텍스트 하나의 길이이고, max_width 채워야 할 전체 너비를 나타내며, inner_widthwhile 내부를 돌기 위한 조건 변수로 두었다. 그리고 애니메이션은 anime.js를 이용해서 무한으로 오른쪽에서 왼쪽으로 돌도록 만들었다.


후기

간단한 동작이라 라이브러리를 찾지 않고 직접 구현했다. 그러나 여전히 zepto나 anime.js의 라이브러리 사용법을 찾는다고 적지 않은 시간을 할애했다. 두 라이브러리는 앞으로도 두고두고 쓸 것 같으니 뭐 이정도 선에서 깔끔하게 구현한 걸 만족한다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다

Scroll to top