当前位置: 首页 > 工具软件 > React Motion > 使用案例 >

React: Animation

林彬
2023-12-01

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的内容;
但此时close的animation会被忽略,因为modal在app中不被render,其css中设定的class也不会显示,会直接消失;

因此需要用到React transition group 进行优化

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>
    );
};

将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(“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")}
        >

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;
}

自定义ClassNames

在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>

对ul li设定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

 类似资料:

相关阅读

相关文章

相关问答