React 動畫 Animation

文章源自: https://facebook.github.io/react/docs/animation.htmlcss

ReactCSSTransitionGroup 基於 ReactTransitionGroup ,當一個React組件enter或者leave時能夠方便的用來執行CSS transitions和animations。html

導入ReactCSSTransitionGroup

import ReactCSSTransitionGroup from 'react-addons-css-transition-group' // ES6
var ReactCSSTransitionGroup = require('react-addons-css-transition-group') // ES5 with npm
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup; // ES5 with react-with-addons.js

定義組件

var React = require('react');
var ReactDOM = require('react-dom');
var CSSTransitionGroup = require('react-addons-css-transition-group');
var INTERVAL = 2000;

var AnimateDemo = React.createClass({
    getInitialState: function() {
        return {current: 0};
    },

    componentDidMount: function() {
        this.interval = setInterval(this.tick, INTERVAL);
    },

    componentWillUnmount: function() {
        clearInterval(this.interval);
    },

    tick: function() {
        this.setState({current: this.state.current + 1});
    },

    render: function() {
        var children = [];
        var pos = 0;
        var colors = ['red', 'gray', 'blue'];
        for (var i = this.state.current; i < this.state.current + colors.length; i++) {
            var style = {
                left: pos * 128,
                background: colors[i % colors.length]
            };
            pos++;
            children.push(<div key={i} className="animateItem" style={style}>{i}</div>);
        }
        return (
            <CSSTransitionGroup
            className="animateExample"
            transitionEnterTimeout={1500}
            transitionLeaveTimeout={1500}
            transitionName="example">
            {children}
            </CSSTransitionGroup>
        );
    }
});

注意: 必須給 ReactCSSTransitionGroup 中的每個child設置一個key屬性,即便只渲染一個elementreact

在這個組件中,當添加一個元素到 ReactCSSTransitionGroup 中時,這個元素將會自動添加上 example-enter 和 example-enter-active 樣式。添加上的樣式基於 transitionName 這個屬性來設置。咱們須要作的就是定義example-xxx等樣式;git

.example-enter,
.example-leave {
    -webkit-transition: all 2s;
    transition: all 2s;
}

.example-enter { /* begin **/
    opacity: 0.01;
    margin-left: 128px;
}

.example-enter.example-enter-active { /* finish **/
    opacity: 1;
    margin-left: 0;
}

.example-leave {
    opacity: 1;
    margin-left: 0;
}

.example-leave.example-leave-active {
    opacity: 0.01;
    margin-left: -128px;
}

.animateExample {
    display: block;
    height: 128px;
    position: relative;
    width: 384px;
}

.animateItem {
    color: white;
    font-size: 36px;
    font-weight: bold;
    height: 128px;
    line-height: 128px;
    position: absolute;
    text-align: center;
    -webkit-transition: all 1s; /* TODO: make this a move animation */
    transition: all 1s; /* TODO: make this a move animation */
    width: 128px;
}

example-enter和example-enter-active分別表示動畫開始和動畫結束時的樣式定義;github

動畫時間在css樣式表中和render方法中,都必須指定,時間用來告訴React何時去移除animation樣式以及何時從DOM中移除元素。web

初始加載動畫

ReactCSSTransitionGroup 提供了可選的屬性 transitionAppear ,用來指定組件初始加載時的動畫,該屬性默認值是false,因此在組件加載的時候默認是沒有動畫的; npm

return (
     <CSSTransitionGroup
            className="animateExample"
            transitionAppear={true}
            transitionAppearTimeout={1500}
            transitionEnterTimeout={1500}
            transitionLeaveTimeout={1500}
            transitionName="example">
             {children}
     </CSSTransitionGroup>
);

修改組件的render方法,而且在css中定義example-appear, example-appear-active樣式;api

.example-appear {
    opacity: 0.01;
    margin-left: 128px;
}

.example-appear.example-appear-active {
    opacity: 1;
    margin-left: 0;
}

這樣在組件初始加載的時候,也會有動畫了!app

組件第一次加載的時候,執行的動畫是appear,以後再有element動態添加到CSSTransitionGroup,將會執行enter動畫,而不會是appear動畫;dom

transitionEnter和transitionLeave默認值是true,因此若是不把它們指定爲false的話得指定transitionEnterTimeout和transitionLeaveTimeout。

自定義Classes

除了經過transitionName指定樣式,還能夠指定每一步的動畫樣式,其中,active樣式名能夠不用指定;

// ...
<ReactCSSTransitionGroup
  transitionName={ {
    enter: 'enter',
    enterActive: 'enterActive',
    leave: 'leave',
    leaveActive: 'leaveActive',
    appear: 'appear',
    appearActive: 'appearActive'
  } }>
  {item}
</ReactCSSTransitionGroup>

<ReactCSSTransitionGroup
  transitionName={ {
    enter: 'enter',
    leave: 'leave',
    appear: 'appear'
  } }>
  {item2}
</ReactCSSTransitionGroup>
// ...

Animating One or Zero Items

上面所實現的動畫,都是整個Group中的元素都將被設置動畫,實際上還能夠指定只須要某一/零個元素執行動畫;

import ReactCSSTransitionGroup from 'react-addons-css-transition-group';

function ImageCarousel(props) {
  return (
    <div>
      <ReactCSSTransitionGroup
        transitionName="carousel"
        transitionEnterTimeout={300}
        transitionLeaveTimeout={300}>
        <img src={props.imageSrc} key={props.imageSrc} />
      </ReactCSSTransitionGroup>
    </div>
  );
}

Animation Group Must Be Mounted To Work

爲了組child添加動畫屬性,ReactCSSTransitionGroup 必須已經被加載到DOM中,或者將 transitionAppear 設置成true。

render() {
  const items = this.state.items.map((item, i) => (
    <div key={item} onClick={() => this.handleRemove(i)}>
      <ReactCSSTransitionGroup transitionName="example">
        {item}
      </ReactCSSTransitionGroup>
    </div>
  ));

  return (
    <div>
      <button onClick={this.handleAdd}>Add Item</button>
      {items}
    </div>
  );
}

上面這個例子將不會起做用,由於ReactCSSTransitionGroup被加載到新的div中,而不是已經加載好的元素當中,且沒有設置transitionAppear。

Disabling Animations 

還能夠禁止掉enter或者是leave動畫,好比但願有enter動畫而不想要leave動畫,可是ReactCSSTransitionGroup須要等待動畫完成後才從dom中remove元素,此時能夠經過設置transitionEnter={false}或者transitionLeave={false}來禁止相應的動畫;

在ReactCSSTransitionGroup中,沒有動畫完成的監聽,因此若是想要獲取到動畫的執行進度而且添加其它操做是不可行的,若是確實有須要,可使用ReactTransitionGroup

相關文章
相關標籤/搜索