アニメーション
Reactはアニメーションの低階層APIとしてReactTransitionGroup
アドオンのコンポーネントと、
基本的なCSSのアニメーションとトランジションの実装を簡単にするReactCSSTransitionGroup
を提供します。
高レベルAPI: ReactCSSTransitionGroup
ReactCSSTransitionGroup
はReactTransitionGroup
を基盤として、
ReactのコンポーネントがDOMに差し込まれる際、または取り去られる際のCSSトランジションとアニメーション操作を簡単にてくれます。
これは、素晴らしいライブラリであるng-animateに影響を受けています。
はじめに
ReactCSSTransitionGroup
は、ReactTransitions
へのインターフェースです。
これはアニメーションさせたい全てのコンポーネントを囲うシンプルな要素です。
下記は、リスト項目をフェードイン、フェードアウトさせる例です。
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
var TodoList = React.createClass({
getInitialState: function() {
return {items: ['hello', 'world', 'click', 'me']};
},
handleAdd: function() {
var newItems =
this.state.items.concat([prompt('Enter some text')]);
this.setState({items: newItems});
},
handleRemove: function(i) {
var newItems = this.state.items;
newItems.splice(i, 1);
this.setState({items: newItems});
},
render: function() {
var items = this.state.items.map(function(item, i) {
return (
<div key={item} onClick={this.handleRemove.bind(this, i)}>
{item}
</div>
);
}.bind(this));
return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
<ReactCSSTransitionGroup transitionName="example">
{items}
</ReactCSSTransitionGroup>
</div>
);
}
});
注意:
例え単一の項目のみを描画するとしても、
ReactCSSTransitionGroup
の全ての子に、key属性を提供しなければいけません。
これはReactが、子が差し込まれるのか、取り除かれるのか、そのままにするのかを決定するためです。
このコンポーネント内で新しい項目がReactCSSTransitionGroup
に追加されると、
その項目はexample-enter
のCSSクラスを取得し、
その後に追加されるとexample-enter-active
を取得します。(翻訳に自信なし)
これは、transitionName
プロパティに基いて行われます。
これらのクラスを、CSSアニメーションまたはトランジションをトリガするのに使用することが出来ます。 例えば、このCSSを追加して新しい項目を追加してみて下さい。
.example-enter {
opacity: 0.01;
transition: opacity .5s ease-in;
}
.example-enter.example-enter-active {
opacity: 1;
}
あなたは項目を削除した際に、ReactCSSTransitionGroup
がその項目をDOM内に保持することに気が付くでしょう。
アドオンを使用したReactでminify無しのビルドを使用している場合、
「Reactはアニメーションとトランジションが発生することを期待していた」という旨の警告が表示されます。
これは、アニメーションが完了するまでReactCSSTransitionGroup
がDOM要素をページ上に保持するためです。
このCSSを追加してみて下さい。
.example-leave {
opacity: 1;
transition: opacity .5s ease-in;
}
.example-leave.example-leave-active {
opacity: 0.01;
}
動作させるためには、アニメーショングループはマウント済みでなければいけない
トランジションを子に対して適用するためには、
ReactCSSTransitionGroup
は予めDOM内にマウントされていなければいけません。
下記の例は、新しい項目がReactCSSTransitionGroup
内にマウントされるのでは無く、
ReactCSSTransitionGroup
が新しい項目と一緒にマウントされるため動作しません。
この例と、前述した「はじめに」の例との違いを比較してみて下さい。
render: function() {
var items = this.state.items.map(function(item, i) {
return (
<div key={item} onClick={this.handleRemove.bind(this, i)}>
<ReactCSSTransitionGroup transitionName="example">
{item}
</ReactCSSTransitionGroup>
</div>
);
}, this);
return (
<div>
<button onClick={this.handleAdd}>Add Item</button>
{items}
</div>
);
}
1つの項目、または項目が無い状態からのアニメーション
上記の例では、ReactCSSTransitionGroup
内に項目のリストを描画していますが、
ReactCSSTransitionGroup
の子を1つの項目、または無しにすることが可能です。
これは、単一の要素の差し込みまたは取り除きのアニメーションを可能にしてくれます。
同じように、新しい要素が入り現在の要素が消える置換アニメーションを作ることも可能です。
例えば、下記のようにシンプルな画像カルーセルを実装することが可能です。
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
var ImageCarousel = React.createClass({
propTypes: {
imageSrc: React.PropTypes.string.isRequired
},
render: function() {
return (
<div>
<ReactCSSTransitionGroup transitionName="carousel">
<img src={this.props.imageSrc} key={this.props.imageSrc} />
</ReactCSSTransitionGroup>
</div>
);
}
});
アニメーションの無効化
必要であれば、差し込みアニメーション、または取り除きアニメーションを無効にすることが出来ます。
例えば、差し込みはアニメーションさせて、取り除きのアニメーションはさせたくないと考えるかもしれませんが、
ReactCSSTransitionGroup
はDOMノードが削除される前にアニメーションを待ち受けてしまいます。
transitionEnter={false}
またはtransitionLeave={false}
をReactCSSTransitionGroup
に追加することで、
これらのアニメーションを無効化することが出来ます。
注意:
ReactCSSTransitionGroup
を使用している場合、
トランジションが終了した、またはアニメーションに関する何らかのより複雑な処理が実行されている時に、
コンポーネントがその事を検知する方法は存在しません。
もし、よりきめ細かい制御をしたいのであれば、
トランジションをカスタマイズするのに必要なフックを提供するReactTransitionGroup
の低レベルAPIを使用します。
低レベルAPI: ReactTransitionGroup
ReactTransitionGroup
はアニメーションの基礎となるものです。
これは、React.addons.TransitionGroup
としてアクセス可能です。
子が宣言的にここから追加または削除されると(前述した例のように)、
特別なライフサイクルのフックが子(コンポーネント?)上で呼び出されます。
異なるコンポーネントを描画
デフォルトでReactTransitionGroup
はspan
を描画します。
これは、コンポーネントにプロパティを提供することで変更可能です。
例えば、下記では<ul>
を描画しています。
<ReactTransitionGroup component="ul">
...
</ReactTransitionGroup>
Reactが描画出来る各DOMコンポーネントで使用することが出来ます。 ただし、コンポーネントはDOMコンポーネントである必要はありません。 あなたが必要とするものであれば、自分自身で書いたReactのコンポーネントでも構いません。
注意:
v0.12より前のバージョンでは、DOMコンポーネントを使用する際は、
コンポーネントのプロパティは、React.DOM.*
への参照である必要がありました。
コンポーネントは単純にReact.createElement
に渡されるので、
今は文字列で無ければいけません。
混合のコンポーネントはファクトリーに渡されなければいけません。
加えて、ユーザー定義プロパティは描画されたコンポーネントのプロパティになります。 例えば、下記はCSSクラスのある<ul>を描画する際の方法になります。
<ReactTransitionGroup component="ul" className="animated-list">
...
</ReactTransitionGroup>