React: Animation
49659 ワード
DIsplay——表示と非表示
classとpropsの判断を利用してbackdropを表示/非表示に変換する.modal
.CloseModal{
display: none;
}
.OpenModal{
display: block;
}
const modal = (props) => {
const cssClasses=["Modal",props.show?"OpenModal":"CloseModal"];
return (
<div className={cssClasses.join(" ")}>
<h1>A Modal</h1>
<button className="Button" onClick={props.closed}>Dismiss</button>
</div>
);
};
backDrop
.CloseBackdrop{
display: none;
}
.OpenBackdrop{
display: block;
}
const backdrop = (props) => {
const cssClasses=["Backdrop",props.show?"OpenBackdrop":"CloseBackdrop"];
return(
<div className={cssClasses.join(" ")}></div>
);
};
app stateとbutton制御backdropの表示非表示を設定
class App extends Component {
state={
ShowModal:false
};
OpenModal=()=>{
this.setState({ShowModal:true})
}
CloseModal=()=>{
this.setState({ShowModal:false})
}
render() {
return (
<div className="App">
<h1>React Animations</h1>
<Modal
show={this.state.ShowModal}
closed={this.CloseModal}
/>
<Backdrop
show={this.state.ShowModal}
/>
<button
className="Button"
onClick={this.OpenModal}
>Open Modal</button>
<h3>Animating Lists</h3>
<List />
</div>
);
}
}
Css Transitions
CSS:設定opacity:0イコールdisplay:none設定opacity:1イコールdisplay:block
.CloseModal{
opacity: 0;
transform: translateY(-200%);
}
.OpenModal{
opacity: 1;
transform: translateY(0);
}
Transitionは、すべてのopacityとtransformにダイナミックエフェクトを追加します.
transition: all 0.3s ease-out;
Animation+keyframes
transitionの各期間の制御を実現
.CloseModal{
animation: close 0.4s ease-out forwards;
}
.OpenModal{
animation: open 0.4s ease-out forwards;
}
@keyframes open{
0%{
opacity: 0;
transform: translateY(-200%);
}
50%{
opacity: 0.5;
transform: translateY(100%);
}
100%{
opacity: 1;
transform: translateY(0);
}
}
@keyframes close{
100%{
opacity: 0;
transform: translateY(-200%);
}
50%{
opacity: 0.5;
transform: translateY(100%);
}
0%{
opacity: 1;
transform: translateY(0);
}
}
制限css transition&animations Limitation
すべての要素はdomにありますが、opacityは0なので隠されています.表示されない要素がrenderされないようにreactでstateに従ってrenderの内容を設定します.しかし、modalはappでrenderされず、cssで設定されたclassも表示されず、直接消えるため、closeのanimationは無視されます.
そのためReact transition groupを用いて最適化する必要がある
https://github.com/reactjs/react-transition-group
import {Transition} from 'react-transition-group';
Transitionの使い方:小包を1つ{function=>(JSX)}
<Transition
in={this.state.ShowToggle}
timeout={300}
mountOnEnter
unmountOnExit
>
{
(state)=>(
<div
style={{
backgroundColor:"red",
width:100,
height:100,
margin:"auto",
transition: 'opacity 0.3s ease-out',
opacity: state==='exiting'||state==='entering'? 0:1
}}></div>
)}
</Transition>
Transitionのstateを下層に転送し、cssカスタマイズを行う
<Transition
in={this.state.ShowModal}
timeout={300}
mountOnEnter
unmountOnExit
>
{
state=>(
<Modal
show={state}
closed={this.CloseModal}
/>
)
}
</Transition>
下層:
const modal = (props) => {
const cssClasses=["Modal",
props.show==='entering'?"OpenModal":
props.show==='exiting'? "CloseModal"
: null];
return (
<div className={cssClasses.join(" ")}>
<h1>A Modal</h1>
<button className="Button" onClick={props.closed}>Dismiss</button>
</div>
);
};
Transitionをcomponentに入れる
import React from 'react';
import './Modal.css';
import {Transition} from 'react-transition-group';
const modal = (props) => {
return (
<Transition
in={props.show}
timeout={300}
mountOnEnter
unmountOnExit
>
{state=>{
const cssClasses=["Modal",
state==='entering'?"OpenModal":
state==='exiting'? "CloseModal"
: null];
return(
<div className={cssClasses.join(" ")}>
<h1>A Modal</h1>
<button className="Button" onClick={props.closed}>Dismiss</button>
</div>
);
}}
</Transition>
);
};
export default modal;
Timingの設定
TransitionのTimeoutはenteringとexitingの時間を指す.この時間がcssでtransitionの時間よりはるかに小さい場合、timeout時間が過ぎた後にenteredまたはexited状態に直接到達し、完全なアニメーションを完了できません.Timeout timeoutのenterとexitを設定すると、openとcloseのtimeout時間をそれぞれ設定できます.
<Transition
in={this.state.ShowToggle}
timeout={300}
mountOnEnter
unmountOnExit
>
{
(state)=>(
<div
style={{
backgroundColor:"red",
width:100,
height:100,
margin:"auto",
transition: 'opacity 0.3s ease-out',
opacity: state==='exiting'||state==='entering'? 0:1
}}></div>
)}
</Transition>
Transitionのevent&callbackの設定
onEnter={()=>>console.log("OnEnter")}onEntering={()=>>console.log("OnEntering")}onEntered={()=>>console.log("OnEntering")}onExit={()=>console.log(""""""""""""""""""""")}onExiting={()=>>console.log(")}onExited={()=>>>console.log(")}6時間帯("Exited")}6時間帯"}6時間帯(""""""""""""""""""""""";
<Transition
in={this.state.ShowToggle}
timeout={300}
mountOnEnter
unmountOnExit
onEnter={()=>console.log("OnEnter")}
onEntering={()=>console.log("OnEntering")}
onEntered={()=>console.log("OnEntering")}
onExit={()=>console.log("OnExit")}
onExiting={()=>console.log("OnExiting")}
onExited={()=>console.log("OnExited")}
>
CSSTransition
CSSTansitionでclassnamesを設定し、cssファイルでname-enter-activeとname-exit-acitveを設定してアニメーションを完了します.
import React from 'react';
import './Modal.css';
import {Transition,CSSTransition} from 'react-transition-group';
const modal = (props) => {
const AnimationTime={
enter:300,
exit:1000
}
return (
<CSSTransition
in={props.show}
timeout={AnimationTime}
mountOnEnter
unmountOnExit
classNames="My-Modal"
>
<div className="Modal">
<h1>A Modal</h1>
<button className="Button" onClick={props.closed}>Dismiss</button>
</div>
</CSSTransition>
);
};
export default modal;
.My-Modal-enter-active{
animation: open 0.4s ease-out forwards;
}
.My-Modal-exit-active{
animation: close 1s ease-out forwards;
}
カスタムClassName
classNameで各パラメータを設定します.
<CSSTransition
in={props.show}
timeout={AnimationTime}
mountOnEnter
unmountOnExit
classNames={{
enterActive:"OpenModal",
exitActive:"CloseModal"
}}
>
<div className="Modal">
<h1>A Modal</h1>
<button className="Button" onClick={props.closed}>Dismiss</button>
</div>
</CSSTransition>
ulliにanimationを設定する
TransitionGroupを使用してCSSTransitionをラップします.
import {TransitionGroup,CSSTransition, Transition} from 'react-transition-group';
cssで対応するtrunk classnameにanimationを設定すればよい.
render () {
const listItems = this.state.items.map( (item, index) => (
<CSSTransition
key={index}
classNames="fade"
timeout={300}
>
<li
className="ListItem"
onClick={() => this.removeItemHandler(index)}>{item}</li>
</CSSTransition>
) );
return (
<div>
<button className="Button" onClick={this.addItemHandler}>Add Item</button>
<p>Click Item to Remove.</p>
<TransitionGroup
component="ul"
className="List"
>
{listItems}
</TransitionGroup>
</div>
);
}
.fade-enter{
opacity: 0;
}
.fade-enter-active{
opacity: 1;
transition: opacity 0.3s ease-out;
}
.fade-exit{
opacity: 1;
}
.fade-exit-active{
opacity: 0;
transition: opacity 0.3s ease-out;
}
その他のanimation library
More on CSS Transitions: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions More on CSS Animations: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations More on ReactTransitionGroup: https://github.com/reactjs/react-transition-group Alternative => React Motion: https://github.com/chenglou/react-motion Alternative => React Move: https://github.com/react-tools/react-move Animating Route Animations: https://github.com/maisano/react-router-transition