下記のような簡単なオープニングアニメーションを実装してみたので書き残しておきます。
実装には GSAP の TimelineMax を使っています。
*参考
- GreenSock-JS / GitHub
- Greensock / TweenMax
- Greensock / TimelineMax
- Vue.js + GSAP = Animations
- アニメーションライブラリのデファクトスタンダード
*環境
- MacOS
- CSS3
- nuxt 2.8.1
- gsap 2.1.3
*TweenMax とは
JavaScript のアニメーションライブラリとして知名度が高い、GSAP(GreenSock Animation Platform)のモジュールのひとつです。高速かつ軽量で、複雑なアニメーションでも比較的簡単に実装できるといった特徴があります。GSAP は下記の4種類で構成されています。
- TweenMax ------- トゥイーンを制御するモジュール
- TweenLite -------- TweenMaxの軽量版
- TimelineMax ---- 複数のトゥイーンやタイムラインを制御するモジュール
- TimelineLite ----- TimelineMaxの軽量版
*TimelineMax とは
時間を軸にしてアニメーションを実行していきます。インスタンスを作成したあとに
to()
、from()
、fromTo()
を使ってアニメーションを追加します。- to ---- 変化後のアニメーションを設定
- from ---- 設定した値から初期値に変化させる(
to
とは逆) - fromTo ---- 初期値と変化後を設定して変化させる
*GSAPのインストール
以前に書いた Nuxt.js + ScrollMagic を使ったスクロールエフェクト の記事で実行しているvue-scrollmagic
をインストールするとGSAP
も同時にインストールされます。個別にインストールしたい場合は
npm install gsap
を実行します。*オープニングアニメーションの実装
今回は Nuxt のプロジェクトで使ったので、Vueファイルに実装しています。下記では、オープニングアニメーションで「mogumogu…」を表示させ、そのあとに「Finished eating!」と表示させています。
まず、
gsap
からTweenMax
とTimelineMax
をインポートしmounted()
でアニメーションの実装をしていきます。TimelineMax
でアニメーションを追加していく方法には2種類あり、timeline.add(TweenMax.to(...))
と書く方法と、timeline.to(...)
を使って書く方法があります。今回は試しにどちらも使っていますが、個人的にはto()
を使ったほうが可読性が良さそうだと思っています。to()
の引数にはto(対象の要素, 秒数, アニメーションのスタイル)
を指定します。スタイルにはopacity
を指定して、非表示の状態から徐々に表示していき、最後はscale
で文字を拡大させながら非表示にしています。<index.vue>
<template>
<div class="page-index">
<div class="title-opening">
<p id="title">mogumogu...</p>
</div>
<div class="effect-delay-display">
<section>
<p>Finished eating!</p>
</section>
</div>
</div>
</template>
<script>
import { TweenMax, TimelineMax } from 'gsap'
export default {
mounted() {
const timeline = new TimelineMax()
timeline
.add([
TweenMax.to('#title', 0.1, {
css: {
position: 'absolute',
opacity: '0',
width: '100px',
right: '40%',
height: '50px',
overflow: 'hidden'
}
})
])
.to('#title', 1, {
css: {
width: '120px',
opacity: '0.5'
}
})
.to('#title', 2, {
css: {
width: '300px',
opacity: '1'
}
})
.to('#title', 2.5, {
css: {
opacity: '0',
scale: '1.5'
}
})
}
}
</script>
<style scoped lang="scss">
.title-opening {
position: absolute;
top: 50vh;
margin: auto;
text-align: center;
width: 85vw;
font-size: 30px;
word-break: break-all;
}
</style>
また「mogumogu…」の文字が左から右に徐々に表示されるようにしたかったので、最初は表示幅を狭くしてわざと文字が切れるようにし、徐々に幅を広げて全体が表示されるようにしています。
*オープニング後の表示
最初のオープニングアニメーション実行中は、その後に表示する「Finished eating!」を非表示にしておきたいので、animation-delay
を使って 5 秒後に表示するようにしています。このときanimation-fill-mode: backwards
を指定しておかないと、オープニングに表示されたままになってしまいます。<_effect.scss>
.effect-delay-display {
animation-name: disp-delay;
animation-delay: 5s;
animation-duration: 1s;
animation-iteration-count: 1;
animation-fill-mode: backwards;
}
@keyframes disp-delay {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
*所感
オープニング後に表示される文字にも別のアニメーション(フェードイン)を付けているため、animation
プロパティで表示を遅らせるようにしましたが、こちらもTimelineMax
を使ったほうが簡単にできるかもしれないです。また、オープニングの文字列が左から右に徐々に表示されるようにしてみたのですが、アニメーションが滑らかでないのでもっと良い方法を探してみたいと思います。ベストプラクティスについては模索中なのですが、アニメーションが複数になると実装が複雑になりそうなので、管理しやすい実装を心掛けていきたいと思っています。
Sign up here with your email
ConversionConversion EmoticonEmoticon