reactを使ってアニメーションをさせたいなんて時もあるのではないでしょうか。日本語のものがそこまでないのがちょっと残念ですが、それでも探してみればライブラリは色々あります。
今回は、react-transition-groupというものを使ってCSSのアニメーションを実装していきたいと思う。
react-transition-groupを使う
<CSSTransition></CSSTransiton>
で囲うことによって囲ったものに対してCSSアニメーションを設定することができる。
<CSSTransiton>
にclassNames
を指定することによって、以下のクラスが適用されるようになる。
- enter
- enter-active
- enter-active-done
- exit
- exit-active
- exit-done
- appear
- appear-active
例えば、<CSSTransition classNames="fade">
のようにすると以下のようなクラスが適用されます。
- fade-enter(追加時)
- fade-enter-active(追加中)
- fade-enter-done(追加完了?)
- fade-exit(削除時)
- fade-exit-active(削除中)
- fade-exit-done(削除完了?)
- fade-appear(マウント時)
- fade-appear-active(マウント中)
自動的に設定されたくない場合は、以下のように詳細に設定することも可能です。
classNames={{ appear: 'my-appear', appearActive: 'my-active-appear', enter: 'my-enter', enterActive: 'my-active-enter', enterDone: 'my-done-enter, exit: 'my-exit', exitActive: 'my-active-exit', exitDone: 'my-done-exit, }}
文字の追加時にアニメーションを行う
以下を使ってアニメーションを実行したいと思います。
- enter
- enter-active
- exit
- exit-active
文字を入力し、その文字が表示された時と削除時ににアニメーションさせたいと思います。
When the in prop is toggled to true the Component will get the example-enter CSS class and the example-enter-active CSS class added in the next tick. This is a convention based on the classNames prop.
in
というものを使って、それがtrueに変わった時にしかenter
とenter-active
は使えないようです。なので、stateのtrueとfalseを入力する毎に入れ替えて、文字が入力されるたびにアニメーションさせたいと思います。
import React from 'react'; import ReactDOM from 'react-dom'; import { CSSTransition } from 'react-transition-group'; import './styles.css'; class Example extends React.Component { constructor(props){ super(props); this.state = ({ name: "", judge: false }); } handleChange(name) { this.setState({ name: name, judge: !this.state.judge }); } render() { return( <div> <input type="text" onChange={ e => this.handleChange(e.target.value)}></input> <CSSTransition in={this.state.judge} classNames="input" > <p>{ this.state.name }</p> </CSSTransition> </div> ); } } ReactDOM.render( <Example />, document.getElementById('root') );
.input-enter { opacity: 0.1; transform: scale(0.9) translateY(50%); } .input-enter-active { opacity: 1; transform: scale(1) translateY(0%); transition: all 300ms ease-out; } .input-exit { opacity: 1; transform: scale(1) translateY(0%); } .input-exit-active { opacity: 0.1; transform: scale(0.9) translateY(50%); transition: all 300ms ease-out; }
これを実行してみると以下のような感じになります。
文字が入力されるたびに文字が出たり消えたりしていますね。ただ、ちょっとこれではcssの反映が分かりにくいので、enter時とexit時の動作を色付きで確認してみます。
cssを以下のようにして、再度確認してみましょう。background-colorで赤と緑を指定したので、文字の追加時に赤から緑に色が変わるはずです。
.input-enter { opacity: 0.1; background-color: red; transform: scale(0.9) translateY(50%); } .input-enter-active { opacity: 0.7; background-color: green; transform: scale(1) translateY(0%); transition: all 300ms ease-out; }
文字を入力すると背景色が変わるのが確認できますね。
文字を削除した時の挙動も確認しておきましょう。文字を削除する時に背景色を黒から黄色に変えるとします。
.input-exit { opacity: 0.7; background-color: black; transform: scale(1) translateY(0%); } .input-exit-active { opacity: 0.1; background-color: yellow; transform: scale(0.9) translateY(50%); transition: all 300ms ease-out; }
こっちも一瞬ですが黒から黄色になっていますね。 組み合わせるとこんな感じになります。
マウント時にcssを追加する
マウント時に動作するのは以下です。
- appear
- appear-active
propsにtrueのin
とappear
が必要なので渡しておきます。
<CSSTransition in classNames="hoge" appear={true} > <p>hoge</p> </CSSTransition>
.hoge-appear { opacity: 0.4; background-color: black; } .hoge-appear-active { opacity: 0.9; background-color: yellow; transition: opacity 500ms ease-in; }
色が表示されますね。
doneの使い道
enter-doneやexit-doneの使い道が正直よく分からない。https://github.com/reactjs/react-transition-groupのCSSTransition.jsでインポートしているTransition.jsの中でIn the context of a TransitionGroup all enters are really appears
とコメントがなされているが、これは・・・実際は、全てappearsになるような想定なのだろうか。