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つなのではないかと思います。