본문 바로가기
UI. UX

[웹애니메이션] anime.js 튜토리얼

by 나나 (nykim) 2018. 4. 25.
Document

anime.js

웹 애니메이션과 anime.js

anime.js는, CSS를 주로 다루는 사람들에게 친숙한 구문으로 DOM을 조작해 웹 애니메이션을 구현하는 라이브러리입니다.

웹 애니메이션은 크게 2가지로 나눠볼 수 있는데, <UI/UX를 위한 애니메이션>과 <독립 애니메이션>입니다.
일반적으로 사용자는 정지 화면보다 움직이는 화면에서 정보를 더 잘 얻는다고 합니다. 따라서 UI/UX 애니메이션을 추가하면, 사용자가 Web사이트를 탐색하거나 특정 작업을 수행하는 과정을 도울 수 있습니다.
한편, 독립 애니메이션은 사이트의 컨셉을 표현하기 위해 사용합니다.

CSS3가 나온 지금, 간단한 인터랙션은 CSS만으로 표현할 수 있고 분기가 없는 애니메이션이라면(로딩 애니메이션 등) CSS로 충분히 표현 가능합니다. 대신 관리가 어렵고, 브라우저 호환성이 낮은 만큼 JS로 애니메이션을 구현하는 게 아직까지는 주류라고 합니다.

그래서 그 대안으로 W3C는 SCC, SVG, JS 애니메이션을 통합하고 외부 JS 라이브러리에 의존하지 않는 Web Animations API(WAAPI)를 제정했습니다. 다만 아직까지는 브라우저별 대응이 미흡하며 이를 위한 폴리필이 있습니다. 만약 WAAPI가 프로젝트에 적합하지 않다고 생각되면 JS 애니메이션 라이브러리를 쓰는 게 좋겠죠.

동적 DOM 애니메이션을 위한 라이브러리로는 GSAP, Velocity.js 등이 있으며 여기서는 anime.js를 다뤄보겠습니다. anime.js는 GSAP 등 다른 라이브러리에 비해 가벼운 편입니다. 따라서 다른 큰 라이브러리가 갖고 있는 모든 기능을 필요로 하지 않는다면 사용할 만합니다. 또한, anime.js는 IE 10부터 대응합니다.


Targets

기본 구문

anime.js를 쓰기 위한 기본 구문은 다음과 같습니다.

var myAnime = anime({
   //여기에 코드 작성
});

CSS Selector

anime.js는 CSS처럼 요소를 셀렉팅할 수 있습니다. 이렇게요!

var myAnime = anime({
   targets: '.ball',
   translateX: 500,
});

DOM Node

다음과 같이 DOM 노드를 가져올 수도 있습니다.


var el = document.querySelector("#wrap .ball");

var myAnime = anime({
   targets: el,
   translateX: 500,
});

다수의 대상을 선택하는 것도 가능합니다.


var els = document.querySelectorAll("#wrap .ball");

var myAnime = anime({
   targets: els,
   translateX: 500,
});

Properties

그럼 이제 어떤 속성을 쓸 수 있는지 본격적으로 살펴보죠!

CSS

아래 코드와 같이 CSS 속성을 입력하여 자동으로 트랜지션 효과를 낼 수 있습니다.

var myAnime = anime({
   targets: ".ball",
   opacity: 1,
   left: '200px',
   scale: 2,
   backgroundColor: '#bada00',
   borderRadius: '50%',
});

SVG Attributes

SVG를 다루는 것도 물론 가능합니다.

var myAnime = anime({
   targets: ".mySvg path",
   strokeWidth: 3,
   stroke: "#badaba",
});

Property Parameters

dutaion, delay, easing 값을 줄 수도 있습니다.

var myAnime = anime({
   targets: ".mySvg path",
   strokeWidth: 3,
   stroke: "#badaba",
   duration: 2000,
   delay: 1000,
   easing: 'easeInOutQuart',
});

Specific Property Parameters


var myAnime = anime({
   targets: ".ball",
   translateX: {
      value: 300,
      duration: 1400,
      easing: 'easeInOutSine'
   },
   scale: {
      value: 0.5,
      duration: 2500,
   },
   backgroundColor: {
      value: "#999",
      delay: 1400,
   },
});

Function Based Parameters

함수 기반 설정에는 3개의 매개 변수가 들어갑니다: target, index, targetCount
target 파라미터는 현재 타겟 요소에 대한 참조를 저장하고, index 파라미터는 인덱스 또는 현재 타겟 요소의 위치를 저장합니다. targetCount 파라미터는 타겟 요소의 총 개수를 저장합니다.

이 target 파라미터는 타겟 요소의 일부 특성을 기반으로 애니메이션 값을 설정해야 할 때 유용합니다. (현재 위치에서 얼마만큼 멀어지게 한다던가, 현재 색상에서 몇 %만큼 어둡게 만든다던가 말이죠)

아래 예시에서 ".ball" 요소들은 각각 0, 200, 400, 600... 만큼의 delay값을 가지고 애니메이션 처리됩니다.

var myAnime = anime({
   targets: ".ball",
   translateY: {
      value: 100,
      delay: function(target, index){
         return index * 200;
      },
   },
});

이런 식으로 활용할 수도 있습니다.

var bgColor = ["#000", "#666", "#ccc"];
var myAnime = anime({
   targets: ".ball",
   translateY: {
      value: 100,
      duration: function(target, index){
         return 1000 + (index * 500);
      },
   },
   backgroundColor: function(target,index){
      return bgColor[index];
   },
   loop: true,
   direction: 'alternate',
   easing: 'easeInOutSine',
});

Animation Parameters

애니메이션 파라미터로는 direction, loop 설정이 가능합니다.


  direction: 'alternate' 또는 'reverse'
  loop: true 또는 num //true = 무한 반복,  num = 정한 숫자만큼 반복

Values

Unitless / Specific Unit / Relative

값은 단위없이 입력 가능하며, 단위는 문자열로 입력해야 합니다. += 등을 이용해 상대적인 수치를 입력할 수도 있습니다.

var myAnime = anime({
   targets: ".ball",
   translateY: 50, //Unitless
   rotate: '1.5turn', //Specific Unit
   height: '+=15', //Relative Value
});

Colors

anime.js에서 컬러값은 'blue'와 같이 색상명으로 입력할 수 없고 16진수 또는 RGB 및 HSL 값으로 지정해야 합니다.

Keyframes

대괄호와 중괄호를 이용해 키프레임 기반 변환 애니메이션을 만들 수 있습니다.

var myAnime = anime({
   targets: ".ball",
   translateX: [
      {value: 200, duration: 1000, delay: 500},
   ],
   translateY: [
     {value: 200, duration: 1000, delay: 2000}, 
   ],
   scaleX: [
      {value: 3, duration: 1000, delay: 500},
      {value: 1, duration: 1000},
   ],
   scaleY: [
     {value: 3, duration: 1000, delay: 1500}, 
     {value: 1, duration: 1000, delay: 0},
   ],
   easing: 'easeOutExpo',
});

Timeline

이제까지는 delay를 이용해 애니메이션 시간을 설정했습니다. 그런데 이 방법은 이전 애니메이션의 시간을 계산해야할 뿐만 아니라, 하나의 값을 변경하면 다른 값도 다시 계산해야만 합니다. 이때 anime.timeline() 함수를 사용하여 타임 라인을 만들 수 있습니다.

타임라인에서는 add() 메서드를 사용해 다른 애니메이션을 추가할 수도 있습니다. 타임라인에 추가된 모든 애니메이션은 추가된 순서대로 재생됩니다. 여기에 offset 값을 활용해 재생 순서를 조절할 수 있습니다.
상대적인 offset 값을 사용할 때, 현재 애니메이션의 시작 지점은 바로 전 애니메이션의 타이밍에 상대적으로 결정됩니다.

Baisc Timeline

var basicTimeline = anime.timeline();

basicTimeline //ball1, ball2, ball3가 순서대로 움직입니다.
   .add({
      targets: ".ball1",
      translateY: 120,
      easing: 'easeOutExpo',
   })
   .add({
      targets: ".ball2",
      translateY: 90,
      easing: 'linear',
   })
   .add({
      targets: ".ball3",
      translateY: 60,
   });

Absolute / Relative Offset

var basicTimeline = anime.timeline();

basicTimeline
   .add({
      targets: ".ball1",
      translateY: 120,
      easing: 'linear',
      duration: 1000,
      offset: 3000, // 타임라인이 시작하고 3000ms 후에 시작합니다.
   })
   .add({
      targets: ".ball2",
      translateY: 90,
      easing: 'linear',
      duration: 1000,
      offset: '-=3000' // 이전 애니메이션이 끝나기 3000ms 전에 시작합니다.
   })
   .add({
      targets: ".ball3",
      translateY: 60,
      easing: 'linear',
      duration: 1000,
      offset: '+=3000' // 이전 애니메이션이 끝나고 3000ms 후에 시작합니다.
   });

Baisc Timeline Parameters

var basicTimeline = anime.timeline({
   direction: 'alternate',
   loop: true,
});

basicTimeline
   .add({
      targets: ".ball1",
      translateY: [ {value: 80}, {value: 160}],
      duration: 2000,
   })
   .add({
      targets: ".ball2",
      translateY: [ {value: 90}, {value: 170}],
      duration: 2000,
      offset: 200,
   })
   .add({
      targets: ".ball3",
      translateY: [ {value: 100}, {value: 180}],
      duration: 2000,
      offset: 300,
   });

Parameters Inheritance

var TLParamsInheritance = anime.timeline({
  targets: '.ball',
  delay: function(el, i) { return i * 250 },
  duration: 500,
  easing: 'easeOutExpo',
  direction: 'alternate',
  loop: true
});

TLParamsInheritance
  .add({
    translateX: 250,
  })
  .add({
    opacity: .5,
    translateX: 250,
    scale: 2,
  })
  .add({
    translateX: 0,
    scale: 1
  });

Playback

var myAnimeTL = anime.timeline({
   duration: 1000,
   direction: 'alternate',
   autoplay: false, //자동 시작 방지
   loop: true
});

myAnimeTL
   .add({
      targets: ".svg_a",
      translateY: 30,
      scale: 1.5,
      offset: 100,
   })
   .add({
      targets: ".svg_slash",
      scale: 0.8,
      offset: 100,
   })
   .add({
      targets: ".svg_b",
      translateY: -30,
      scale: 1.5,
      offset: 100,
   });


document.querySelector('.play').onclick = myAnimeTL.play;
document.querySelector('.pause').onclick = myAnimeTL.pause;
document.querySelector('.restart').onclick = myAnimeTL.restart;
document.querySelector('.reverse').onclick = myAnimeTL.reverse;

See the Pen WJrWPX by NY KIM (@nykim_) on CodePen.


Callbacks

Complete

애니메이션이 완료됐을 때 처리는 compete 속성에 function을 설정합니다.
참고로 개별 애니메이션마다 complete가 발생하는 것이 아닌, 만든 anime 객체의 모든 애니메이션이 완료될 때 complete가 발생합니다. 또, loop:true일 때 complete는 동작하지 않습니다.

var logBegin = document.querySelector('.logBegin');
var logComplete = document.querySelector('.logComplete');

var complete = anime({
   targets: '.ball',
   translateY: 100,
   begin: function(anim){
      logBegin.value = 'began: ' + anim.began;
   },
   complete: function(anim){
      logComplete.value = 'completed: ' + anim.completed;
   }
});

'UI. UX' 카테고리의 다른 글

SVG Line Animation  (1) 2018.05.16
Snap.svg (포스팅 테스트 중!)  (0) 2018.04.18