見出し画像

Vue + anime.js でアニメーションを実装してみる

こんにちは。最近はもっぱら marchily という日報・タスク管理サービスを開発しています。

marchily には、ソシャゲによくあるデイリーログインという機能がありまして、そのアニメーションの実装にあたって anime.js というライブラリを利用してみました。この記事では anime.js を使ったアニメーションの実装の流れを紹介します。

anime.js とは

anime.js は JavaScript で DOM をアニメーションさせるライブラリです。

以下のように、アニメーションさせたい要素を targets で指定し、その他のプロパティでどのようにアニメーションさせるかを指定します。この例では、transform: translateX プロパティを変化させることによりアニメーションが動きます。

anime({
  targets: '#cssSelector .el',
  translateX: 250
});

本家のドキュメントでコード + 実際のアニメーションを見ることができるので、こちらを見て理解するのが早いです。普段 CSS アニメーションを書いている人にとっては、馴染みのあるプロパティが網羅されています。

http://animejs.com/documentation/

タイムライン機能

anime.js の大きな特徴としてタイムライン機能があります。この機能を使うと、Flash のタイムラインのように指定したアニメーションを特定の位置まで移動させることができるため、アニメーションをスキップさせて最後の状態を表示させる、といったことが実装可能になります。

var basicTimeline = anime.timeline();

basicTimeline
  .add({
    targets: '#basicTimeline .square.el',
    translateX: 250,
    easing: 'easeOutExpo'
  })
  .add({
    targets: '#basicTimeline .circle.el',
    translateX: 250,
    easing: 'easeOutExpo'
  })
  .add({
    targets: '#basicTimeline .triangle.el',
    translateX: 250,
    easing: 'easeOutExpo'
  });

Vue と組み合わせて実装してみる

anime.js の概要がわかったところで、デイリーログインのアニメーションを実装してみました。先に完成形をお見せすると、以下のようなアニメーションになります。スタンプを押すアニメーションと、今週のタスクを表示するアニメーションに分かれています。

※ 以下のコードは実際のコードではありません。あくまでイメージです

まず、Vue 側で2つに別れるアニメーションを Scene と捉え、状態によって表示する Scene を出し分けるようにします。

<template>
  <div @click.stop="next">
    <div v-show="isFirstScene" ref="first">
      <!-- スタンプを押すアニメーション用の要素を配置 -->
    </div>

    <div v-show="isSecondScene" ref="second">
      <!-- 今週のミッションを表示するアニメーション用の要素を配置 -->
    </div>
  </div>
</template>

Component 側では、mounted のタイミングで showFirstScene を呼んで最初のアニメーションを表示します。

export default {
  data() {
    isFirstScene: true,
    isSecondScene: false,
    firstTimeline: null,
    secondTimeline: null
  },

  mounted() {
    this.showFirstScene();
  },

  methods: {
    showFirstScene() {
      this.isFirstScene = true;
      this.firstTimeline = anime.timeline();

      this.firstTimeline
       .add({})
       .add({})
       ...
    }
  }
}

次にアニメーションのスキップ・切り替えです。
先ほどテンプレート側で、しれっと画面の何処かをクリックしたら next メソッドが呼ばれるようにしておきました。next メソッドが呼ばれたら、現在のアニメーションの進捗に合わせてスキップしたり次のアニメーションに切り替えたりします。

timeline#seek を使うとアニメーションを任意の位置まで進めることができます。また、timeline#completed でタイムラインが終了しているか判断することが可能です。

methods: {
  next() {
    if (this.firstTimeline) {
      if (this.firstTimeline.completed) {
        // 次のアニメーションにうつる
        this.showSecondScene();
      } else {
        // アニメーションの最後までスキップさせる
        this.firstTimeline.seek(this.firstTimeline.duration);
      }
    }
  }
}

以上でアニメーションのスキップ、遷移が実装できます。

なお、実際のコードでは isFirstShow のようなフラグと Timeline をまとめた Scene オブジェクトを生成して扱うようなコードとしています。

最後に

anime.js、最近はそこまで活発に開発されているとは言えなそうですが、そこまで凝ったものではないが CSS で直接書くのは辛いようなアニメーションを作る際には、割と良い選択肢の1つなのではないかと思います。


この記事が気に入ったらサポートをしてみませんか?