Vue で Web Animations をかっこよく実装するライブラリを作ってみた
こんにちは。shundroid です。
あけましておめでとうございます(遅)
10か月振りくらいの投稿ですね。
高校が休みになっているので、勉強・開発に励んでおりました。
そこで、Vue.js で Transition だけでなく、
Web Animations を取り入れたい状況が出てきました。
現状で Vue.js で Web Animations を使う場合
そこで次のようなコードを書いたのですが、
これは Vue.js としてはふさわしくないですよね。
1 | <template> |
どこがふさわしくないのでしょうか。 ref
を使っている辺りが明らかに良くないですけど、
問題はそれ以上にあると考えます。
「動作」で書くか「状態」で書くか
事を大きくしすぎた気もしますが、根本的な問題はここにあると思います。
アニメーションのような 一過性 のものは、一般的には「動作」で書くのがふさわしいですよね。
そのため、 .animate
という メソッド によって「動作」を記述しているのです。
ただし、Vue.js は伝統的に、「動作」による記述よりも「状態」による記述を好みます。
例えば、View上の文字を変更するのに element.updateText('hoge!')
みたいに書いたりはしませんよね。{{ text }}
のような text
という data
の「状態」の記述によって、UIの変更を行っています。
インラインテキストだけでなく、属性やスタイルの変更、また Transition
についても同様に、「状態」による記述を行っています。
これはどうしてでしょうか。Vue.js の存在意義を考えるとこれは明らかです。
先ほども少し触れましたが、「動作」というのは一過的な概念です。
つまり、一回「動作」してしまえば、それが長い間ずっと続くようなことはありません。
ただし、Vue にとっては、これが長い間続いてほしいんですよね。これはなぜか。
まさしく、双方向データバインディング を保つためです。
データのリンクは、動作のように一回一回の時のみかろうじてつなぎ留められているようではいけないのです。
このように Vue で「状態」が重んじられている背景を踏まえると、そこに「動作」で記述されたプログラムを書くのは、
なんだか異物感を感じるわけです。もちろん動きはするんですけど、ちょっと消化不良というか、そういう感覚です。
HTML(XML) は非常に「状態」を書くのに優れた(マークアップ)言語です。
対してJSは「動作」を書くのを主としているわけなので、
例え .animate
メソッドの引数で渡されているオブジェクトが状態だ!と主張したとしても、<template>
タグ内で書けた方がよいですよね。
というわけで、Web Animation を「状態」で記述するようにしたのが、このライブラリです。
コードを見てみましょう。
※ もちろん Vue でも動作を好む場面はあります。 v-on
などに代表されますが、これらで実行される処理は View
の背後の、ロジック的な部分であって、Vue でなくても別に良い部分なわけなので、ここをとって「Vueは動作による記述を好む」というのは言いすぎな気がします。
「状態」で Web Animations を記述する。
インストールは、yarn または npm で行ってください。
1 | $ yarn add vue-animate-component |
または
1 | $ npm i --save vue-animate-component |
コードは次のようになります。
1 | <template> |
Web Animation をタグによって記述できます。 v-model
が true
になった時、
アニメーションの終了は v-model
が false
になったことを検知してください。今後 @finish
などを実装するかもしれませんが。
詳細な利用法は、Github レポジトリをご覧ください。
今後の課題
v-model
がfalse
になった時、アニメーションをpause
する@finish
などのイベントを実装する(「動作」による記述を奨励するようですが…)
余談:実装がスッカスカな話
この実装は Github で見られるんですけど、スッカスカなので試しに keyframes.vue
を見てみましょう
1 | <template> |
えっ()
つまりそういうことなんです。察してください。animation.vue
のほうでは、自分と子要素の $attrs
をそのまま .animate
の引数に丸投げしているだけです。
そんな意味あることなの?と思われるかもしれませんが、大事なのはその変換過程ではなく、
状態は <template>
内で書く、という役割分担がはっきりすることと、
またアニメーションの開始を v-model
による状態変化で行えることであってほしいです(希望)