Shifty 애니메이션 엔진의 핵심: Tweenable 클래스 분석 및 활용

Shifty는 웹에서 가장 빠른 TypeScript 기반 애니메이션 엔진 중 하나로, Tweenable 클래스를 통해 강력한 애니메이션 제어 기능을 제공합니다. 이 문서에서는 Tweenable 클래스의 내부 구현 원리와 고급 사용법을 살펴보며, 개발자가 이를 효과적으로 활용할 수 있도록 안내합니다.

Tweenable 클래스의 기본 구조

Tweenable은 Shifty의 핵심 구성 요소로, src/tweenable.ts 파일에 정의되어 있습니다. 이 클래스는 객체 지향 방식으로 애니메이션 생성, 실행, 관리를 캡슐화하여 다양한 API를 제공합니다.

주요 속성과 초기화

생성자는 초기 상태와 설정 객체를 받아 필요한 속성을 초기화합니다:

constructor(initialState: TweenState = {}, config?: TweenableConfig) {
  this._currentState = initialState;
  if (config) {
    this.applyConfig(config);
  }
}

핵심 속성들은 다음과 같습니다:

  • _currentState: 현재 진행 중인 애니메이션 상태
  • _originalState: 애니메이션 시작 시점의 상태
  • _targetState: 목표 상태
  • _duration: 애니메이션 지속 시간 (기본값 500ms)
  • _easing: 적용된 easing 함수

애니메이션 생명 주기 관리

Tweenable은 애니메이션의 전체 생명 주기를 세밀하게 관리하며, 아래와 같은 주요 메서드를 제공합니다.

tween() - 애니메이션 시작

tween() 메서드는 새로운 애니메이션을 시작하는 진입점입니다. 이미 실행 중인 애니메이션이 있다면 중지하고 새 설정을 적용합니다:

tween(config?: TweenableConfig): Tweenable {
  if (this.isPlaying) {
    this.halt();
  }
  if (config || !this.configExists()) {
    this.applyConfig(config);
  }
  this.startTime = Tweenable.getCurrentTime();
  this.startAnimation(this.currentState);
  return this.continueFrom(this.startTime);
}

applyConfig() - 설정 적용

applyConfig() 메서드는 애니메이션의 시작 상태, 종료 상태, 지속 시간, easing 함수 등을 설정합니다:

applyConfig(config: TweenableConfig = {}): Tweenable {
  // 설정 병합
  // 상태 초기화
  // easing 함수 설정
  this._easing = buildEasingMap(this._currentState, config.easing);
  return this;
}

제어 관련 메서드

다음과 같은 제어 기능들이 포함되어 있습니다:

  • pause(): 애니메이션 일시정지
  • resume(): 일시정지된 애니메이션 재개
  • halt(): 애니메이션 즉시 종료
  • cancel(): 애니메이션 취소 및 Promise 거부
  • jumpTo(time): 특정 시간대로 이동

Easing 시스템 구현

Shifty의 easing 시스템은 성능 향상과 유연성을 위해 설계되었습니다. Tweenable 클래스는 정적 속성 easing을 통해 easing 함수들을 관리합니다:

static easing: Record<string, EasingFunction> = { ...standardEasings };

사용자는 커스텀 easing 함수를 등록할 수 있습니다:

Tweenable.easing['easeInQuad'] = (progress: number) => progress * progress;

또한 베지어 곡선을 이용해 easing 효과를 생성할 수도 있습니다:

import { createBezierCurve } from './bezier';
Tweenable.easing['bounceOut'] = createBezierCurve(0.68, -0.55, 0.735, 0.045);

고급 활용 및 팁

Promise 기반 처리

Tweenable은 Promise 인터페이스를 지원하므로 async/await 문법으로도 쉽게 다룰 수 있습니다:

await new Tweenable().tween({
  from: { scale: 0 },
  to: { scale: 1 },
  duration: 800
});
console.log("애니메이션 완료!");

상태 접근 및 변경

getter/setter를 통해 애니메이션 상태를 동적으로 조작할 수 있습니다:

// 현재 상태 확인
const currentState = tweenable.currentState;

// 상태 업데이트
tweenable.updateState({ rotation: 90 });

데이터 바인딩

bindData() 메서드를 사용하면 DOM 요소나 다른 데이터를 애니메이션 인스턴스에 연결하여 콜백에서 사용할 수 있습니다:

tweenable.bindData({ node: element })
  .tween({
    from: { alpha: 0 },
    to: { alpha: 1 },
    step: (state, meta, boundData) => {
      boundData.node.style.opacity = state.alpha;
    }
  });

필터 확장

Tweenable.filters를 통해 애니메이션 전후 처리를 확장할 수 있으며, 예를 들어 문자열 보간 기능도 구현 가능합니다:

Tweenable.filters['logFilter'] = {
  shouldRun: () => true,
  onCreate: (instance) => console.log('New tween created')
};

성능 최적화 팁

  1. 객체 재사용: 불필요한 인스턴스 생성 대신 기존 인스턴스를 재활용하세요.
  2. 일시정지 활용: 필요할 때만 애니메이션을 실행해야 한다면 새로 만들기보다 pause/resume을 사용하세요.
  3. 리소스 해제: 더 이상 사용하지 않는 인스턴스는 dispose()를 호출하여 메모리를 회수하세요.
  4. 그룹 처리: 여러 애니메이션을 동시에 실행할 경우 공통 타임라인을 사용하는 것이 효율적입니다.

태그: TypeScript Animation Shifty Tweenable easing

8월 4일 04:47에 게시됨