youngwind / blog

梁少峰的个人博客
4.66k stars 385 forks source link

交互动画系列之三:react动画 #57

Open youngwind opened 8 years ago

youngwind commented 8 years ago

react动画问题所在

假设我们要做下面这样的一个卡片切换的动画。 demo 如果用常规的html+js的思路来解决的话是这样的

  1. 两个div
  2. 给第一个div添加退出动画
  3. 给第二个div添加进入动画
  4. 完了

看起来并没有什么难度。 如果用react思维来思考的问题,前后两个卡片其实是一个组件。在react的渲染机制中,一个组件渲染一段DOM元素,当数据改变的时候,渲染新的DOM元素并且直接替换原来的DOM元素,毫无过渡性可言。 也就是说,如果不采取特殊方法的话,同一个组件渲染的DOM元素不可能同时出错在DOM中。

解决思路:

  1. 用两个组件来模拟。把一个组件实例化两遍,但是这样子实现好搓。
  2. 用react本身实现。

我们看第二个思路。其实react原生就有这个工具来处理动画,ReactCSSTransitionGroup

ReactCSSTransitionGroup

具体原理和实现方式上面那个链接已经说得非常明白了,下面我就直接给出我的demo

// style
.demo {
    float: left;
    margin-left: calc(50% - 280px);;
    margin-right: auto;
    width: 560px;
    height: 560px;
    background-color: #eee;
    border-radius: 10px;
    box-shadow: 0px 5px 10px #999;
  }

  .example-enter {
    float: right;
    margin-left: 0;
    margin-right: -600px;
    transition: all 1.5s cubic-bezier(.28, .79, .27, .99) 0.3s;
    box-shadow: 5px 1px 10px #999;
  }

  .example-enter.example-enter-active {
    margin-right: calc(50% - 280px);
    box-shadow: 0px 5px 10px #999;

  }

  .example-leave {
    float: left;
    margin-left: calc(50% - 280px);
    transition: all 1s cubic-bezier(.74, .42, 1, .65);
  }

  .example-leave.example-leave-active {
    margin-left: -600px;
    box-shadow: -5px 1px 10px #999;
  }
// jsx
var ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;

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

    handleClick: function () {
      var index = this.state.index;
      this.setState({
        index: index + 1
      })
    },
    returnWord: function () {
      if (this.state.index) {
        return (
                <div className="demo" onClick={this.handleClick} key={this.state.index}>
                  <h1>{this.state.index}</h1>
                </div>
        )
      } else {
        return (
                <button onClick={this.handleClick}>click me</button>
        )
      }
    },
    render: function () {
      var Word = this.returnWord();
      return (
              <div style={{overflow:"hidden",padding:"20px 0"}}>
                <ReactCSSTransitionGroup transitionName="example">
                  {Word}
                </ReactCSSTransitionGroup>
              </div>
      );
    }
  });

遗留问题:

  1. 目前为止只能控制react动画,但是如果你想在动画结束之后等特殊时间点触发一些事情,那么还需要使用ReactTransitionGroup
  2. 目前组件的动画没问题了,但是container之间切换的话如何使用这个应用动画呢?