利用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:
设置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;
实现对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);
}
}
所有元素都在dom中,只是opacity为0,所以被隐藏;
为使不显示的元素不被render,在react中根据state设置render的内容;
但此时close的animation会被忽略,因为modal在app中不被render,其css中设定的class也不会显示,会直接消失;
https://github.com/reactjs/react-transition-group
import {Transition} from 'react-transition-group';
Transition用法:包裹一个{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>
);
};
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;
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>
onEnter={()=>console.log(“OnEnter”)}
onEntering={()=>console.log(“OnEntering”)}
onEntered={()=>console.log(“OnEntering”)}
onExit={()=>console.log(“OnExit”)}
onExiting={()=>console.log(“OnExiting”)}
onExited={()=>console.log(“OnExited”)}
六个时间段;
<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")}
>
在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;
}
在classNames中设置各个参数;
<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>
使用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;
}
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