EnterAnimation 进场动画

通过简单的配置对一组元素添加串行的进场动画效果。

何时使用

  • 从内容A到内容B的转变过程时能有效的吸引用户注意力,突出视觉中心,提高整体视觉效果。

  • 小的信息元素排布或块状较多的情况下,根据一定的路径层次依次进场,区分维度层级,来凸显量级,使页面转场更加流畅和舒适,提高整体视觉效果和产品的质感。

API

元素依次进场。

<EnterAnimation>
  <div key='demo'>
    <div>依次进场</div>
    <div>依次进场</div>
    <div>依次进场</div>
    <div>依次进场</div>
  </div>
</EnterAnimation>

如子节点有 enter-data 值,则只执行有 enter-data 的节点的动画,相反所有子节点上都没有 enter-data 值,则执行遍历 dom 下一级节点来执行动画。

<EnterAnimation enter={type:'left',delay:2}>
  <div key='demo'>
    <div>
      <div enter-data>
        依次进场
      </div>
    </div>
    <div enter-data>依次进场</div>
    <div enter-data={{type: 'bottom'}}>依次进场,并修改动画效果</div>
    <div>没有动画</div>
  </div>
</EnterAnimation>

参数 类型 默认值 详细
enter object {type:'right'} 管理进场数据
leave object null 管理当前元素出场的数据, null 时继承 enter 里的所有标签的值
component string div EnterAnimation 替换的标签名

enter = {} | leave = {}

参数 类型 默认值 详细
type string right 内置动画样式:
alpha left right top bottom scale scaleBig scaleX scaleY
style object / string null 同上, style 的样式动画, type 有值,此项无效。
{transform:'translateX(100px)'}'transform: translateX(100px)'
duration number 0.5 每个动画的时间,以秒为单位
ease string cubic-bezier(0.165, 0.84, 0.44, 1); 样式缓动,只支持 css 样式缓动;
delay number 0 整个区块的延时,以秒为单位
reverse boolean false 是否倒放,从最后一个 dom 开始往上播放
interval number 0.1 递增延时值,以秒为单位
callback function null 动画结束回调

一级标签key:

参数 类型 详细
key string 必需,控制进出场;

子标签

参数 类型 默认值 详细
enter-data object {type:'right'} 子标签进场参数
leave-data object enter-data 子标签出场参数

enter-data = {} | leave-data = {}

参数 类型 默认值 详细
type string right 同标签里的 type,覆盖标签里的值
style object / string null 同标签里的 style,覆盖标签里的值
duration number 0.5 同标签里的 duration,覆盖标签里的值
ease string cubic-bezier(0.165, 0.84, 0.44, 1) 同标签里的 ease,覆盖标签里的值
delay number 0 当前动画的延时,依照结构递增以上的 interval
queueId number 0 动画的线程

由于使用了 CSS3 动画,所以 IE9 及更早的版本将没有进场效果。

组件演示

var EnterAnimation = antd.EnterAnimation;

React.render(
  <EnterAnimation>
    <ul key="key">
      <li>依次进场</li>
      <li>依次进场</li>
      <li>依次进场</li>
      <li>依次进场</li>
      <li>依次进场</li>
      <li>依次进场</li>
      <li>依次进场</li>
      <li>依次进场</li>
    </ul>
  </EnterAnimation>
, document.getElementById('components-enter-animation-demo-simple'));

最简单的进场例子。

var EnterAnimation = antd.EnterAnimation;

var Test = React.createClass({
  getInitialState() {
    return {
      enter:{
        type: 'right',
        interval: 0.3,
        callback:() => {
          console.log('enter');
        }
      },
      leave:{
        type: 'left',
        interval: .1,
        callback:() => {
          console.log('leave');
        }
      },
      show:true,
    }
  },
  onClick() {
    this.setState({
      show:!this.state.show,

    })
  },
  render() {
    return (
      <div>
        <div style={{marginBottom: 20}}>
          <button className="ant-btn ant-btn-primary" onClick={this.onClick}>切换</button>
        </div>
        <EnterAnimation enter={this.state.enter} leave={this.state.leave}>
          {this.state.show ? 
            <div className="demo-content" key='demo'>
              <div className="demo-kp">
                <ul>
                  <li></li>
                  <li></li>
                  <li></li>
                </ul>
              </div>
              <div className="demo-listBox">
                <div className="demo-list">
                  <div className="title"></div>
                  <ul>
                    <li></li>
                    <li></li>
                    <li></li>
                  </ul>
                </div>
              </div>
          </div> : null}
        </EnterAnimation>
      </div>
    );
  }
});

React.render(<Test />
, document.getElementById('components-enter-animation-demo-enter-leave'));

配置进出场动画样式。

var EnterAnimation = antd.EnterAnimation;

var Test = React.createClass({
  getInitialState() {
    return {
      enter: {
        style: {
          transform: "translateX(50px)",
          opacity: 0
        },
        interval: .1,
      },
      leave: {
        interval: 0.03
      },
      show: true
    }
  },
  onClick() {
    this.setState({
      show: !this.state.show
    })
  },
  render() {
    return (
      <div>
        <div style={{marginBottom: 20}}>
          <button className="ant-btn ant-btn-primary" onClick={this.onClick}>切换</button>
        </div>
        <EnterAnimation enter={this.state.enter} leave={this.state.leave}>
        {this.state.show ? <div key='enter-data'>
          <div className="demo-content">
            <div className="demo-kp">
              <ul>
                <li enter-data></li>
                <li enter-data></li>
                <li enter-data></li>
              </ul>
            </div>
            <div className="demo-listBox">
              <div className="demo-list">
                <div className="title" enter-data={{style: {transform: 'translateY(30px)', opacity: 0}, queueId: 1}}></div>
                <ul>
                  <li enter-data={{style: {transform: 'translateY(30px)', opacity: 0}, queueId: 1}}></li>
                  <li enter-data={{style: {transform: 'translateY(30px)', opacity: 0}, queueId: 1}}></li>
                  <li enter-data={{style: {transform: 'translateY(30px)', opacity: 0}, queueId: 1}}></li>
                </ul>
              </div>
            </div>
          </div>
        </div> : null}
        </EnterAnimation>
      </div>
    )
  }
});

React.render(<Test />
, document.getElementById('components-enter-animation-demo-style'));

通过加上属性里的 style 来自定义 CSS 动画进出场。

var EnterAnimation = antd.EnterAnimation;
var Select = antd.Select;
var Option = Select.Option;
var Checkbox = antd.Checkbox;
var Radio = antd.Radio;
var RadioGroup = antd.Radio.Group;

var Test = React.createClass({
  getInitialState() {
    return {
      enter: {
        type: 'right',
        callback: null,
        interval: 0.1
      },
      leave: {
        type: 'left',
        reverse: true,
        interval: 0.05,
        ease:'cubic-bezier(0.55, 0.085, 0.68, 0.53)',
        callback: ()=> {
          console.log('出场结束')
        }
      },
      show: true
    }
  },
  onClick() {
    this.setState({
      show: !this.state.show
    })
  },
  render() {
    return (
      <div>
        <div style={{marginBottom: 20, textAlign: 'center'}}>
          <button className="ant-btn ant-btn-primary" onClick={this.onClick}>切换</button>
        </div>
        <EnterAnimation enter={this.state.enter} leave={this.state.leave} component='form' className="ant-form-horizontal">
          {this.state.show ? <div key='from'>
            <div className="ant-form-item ant-form-item-compact">
              <label htmlFor="userName" className="col-6" required>用户名:</label>
              <div className="col-6">
                <p className="ant-form-text">大眼萌 minion</p>
              </div>
            </div>
            <div className="ant-form-item">
              <label htmlFor="password" className="col-6" required>密码:</label>
              <div className="col-14">
                <input className="ant-input" type="password" id="password" placeholder="请输入密码"/>
              </div>
            </div>
            <div className="ant-form-item ant-form-item-compact">
              <label  className="col-6" required>您的性别:</label>
              <div className="col-14">
                <RadioGroup value="male">
                  <Radio value="male">男的</Radio>
                  <Radio value="female">女的</Radio>
                </RadioGroup>
              </div>
            </div>
            <div className="ant-form-item">
              <label htmlFor="remark" className="col-6" required>备注:</label>
              <div className="col-14">
                <textarea className="ant-input" id="remark" placeholder="随便写"></textarea>
                <p className="ant-form-explain">随便写点什么</p>
              </div>
            </div>
            <div className="ant-form-item ant-form-item-compact">
              <div className="col-14 col-offset-6">
                <label>
                  <Checkbox />
                  同意
                </label>
              </div>
            </div>
            <div className="row">
              <div className="col-16 col-offset-6">
                <input type="submit" className="ant-btn ant-btn-primary" value="确 定" />
              </div>
            </div>
          </div> : null}
        </EnterAnimation>
      </div>
    )
  }
});

React.render(<Test />
, document.getElementById('components-enter-animation-demo-form'));

表单组合的进场与出场动画。

var EnterAnimation = antd.EnterAnimation;

var Test = React.createClass({
  getInitialState() {
    return {
      show: true
    }
  },
  onClick() {
    this.setState({
      show: !this.state.show
    })
  },
  render() {
    return (
      <div>
        <div style={{marginBottom: 20}}>
          <button className="ant-btn ant-btn-primary" onClick={this.onClick}>切换</button>
        </div>
        <EnterAnimation>
          {this.state.show ?
            <div className="demo-content" key='a'>
              <div className="demo-kp">
                <ul>
                  <li></li>
                  <li></li>
                  <li></li>
                </ul>
              </div>
              <div className="demo-listBox">
                <div className="demo-list">
                  <div className="title"></div>
                  <ul>
                    <li></li>
                    <li></li>
                    <li></li>
                  </ul>
                </div>
              </div>
          </div> : null}
        </EnterAnimation>
      </div>
    );
  }
});

React.render(<Test />
, document.getElementById('components-enter-animation-demo-basic'));

自动。

var EnterAnimation = antd.EnterAnimation;

var Test = React.createClass({
  getInitialState() {
    return {
      enter: {
        type: 'right',
        interval: .1,
      },
      leave: {
        type:'left',
        interval: 0.03
      },
      show: true
    }
  },
  onClick() {
    this.setState({
      show: !this.state.show
    })
  },
  render() {
    return (
      <div>
        <div style={{marginBottom: 20}}>
          <button className="ant-btn ant-btn-primary" onClick={this.onClick}>切换</button>
        </div>
        <EnterAnimation enter={this.state.enter} leave={this.state.leave}>
        {this.state.show ? <div key='enter-data'>
          <div className="demo-content">
            <div className="demo-kp">
              <ul>
                <li enter-data></li>
                <li enter-data></li>
                <li enter-data></li>
              </ul>
            </div>
            <div className="demo-listBox">
              <div className="demo-list">
                <div className="title" enter-data={{type: 'bottom', queueId: 1}}></div>
                <ul>
                  <li enter-data={{type: 'bottom', queueId: 1}}></li>
                  <li enter-data={{type: 'bottom', queueId: 1}}></li>
                  <li enter-data={{type: 'bottom', queueId: 1}}></li>
                </ul>
              </div>
            </div>
          </div>
        </div> : null}
        </EnterAnimation>
      </div>
    )
  }
});

React.render(<Test />
, document.getElementById('components-enter-animation-demo-enter-data'));

通过加上 enter-data 属性来指定需要动画进场的元素,并且可以定义每个元素的动画效果。

var EnterAnimation = antd.EnterAnimation;

var Test = React.createClass({
  getInitialState() {
    return {
      show: true,
      enter:{
        type:'right',
        ease:'cubic-bezier(0.19, 1, 0.22, 1)'
      },
      leave:{
        type:'left',
        ease:'cubic-bezier(0.455, 0.03, 0.515, 0.955)',
        reverse:true,
        interval:0.05
      }
    }
  },
  onClick() {
    this.setState({
      show: !this.state.show
    })
  },
  render() {
    return (
      <div>
        <div style={{marginBottom: 20}}>
          <button className="ant-btn ant-btn-primary" onClick={this.onClick}>切换</button>
        </div>
        <EnterAnimation enter={this.state.enter} leave={this.state.leave}>
          {this.state.show ? <div key='a'>
            <div className="demo-header" enter-data leave-data={{type:'alpha'}}>
              <div className="logo" leave-data={{type:'left'}}>
                <img width="30" src="https://t.alipayobjects.com/images/rmsweb/T1B9hfXcdvXXXXXXXX.svg" />
                <span>logo</span>
              </div>
              <ul >
                <li enter-data leave-data={{type:'right'}}></li>
                <li enter-data leave-data={{type:'right'}}></li>
                <li enter-data leave-data={{type:'right'}}></li>
                <li enter-data leave-data={{type:'right'}}></li>
                <li enter-data leave-data={{type:'right'}}></li>
              </ul>
            </div>
            <div className="demo-content" >
              <div className="demo-title" enter-data={{type:'bottom'}} leave-data={{type:'bottom',queueId:1}}>我是标题</div>
              <div className="demo-kp">
                <ul>
                  <li enter-data={{interval:0.05}} leave-data={{type:'bottom',queueId:1}}></li>
                  <li enter-data={{interval:0.05}} leave-data={{type:'bottom',queueId:1}}></li>
                  <li enter-data={{interval:0.05}} leave-data={{type:'bottom',queueId:1,delay:0.2}}></li>
                </ul>
              </div>
              <div className="demo-title" enter-data={{type:'bottom'}} leave-data={{type:'bottom',queueId:2}}>我是标题</div>
              <div className="demo-listBox">
                <div className="demo-list">
                  <div className="title" enter-data={{type:'bottom'}} leave-data={{queueId:2}}></div>
                  <ul>
                    <li enter-data={{type:'bottom'}} leave-data={{queueId:2}}></li>
                    <li enter-data={{type:'bottom'}} leave-data={{queueId:2}}></li>
                    <li enter-data={{type:'bottom'}} leave-data={{queueId:2}}></li>
                    <li enter-data={{type:'bottom'}} leave-data={{queueId:2}}></li>
                    <li enter-data={{type:'bottom'}} leave-data={{queueId:2}}></li>
                  </ul>
                </div>
              </div>
            </div>
            <div className="demo-footer" enter-data={{type:'bottom'}} leave-data={{queueId:2}}></div>
          </div> : null}
        </EnterAnimation>
      </div>
    );
  }
});

React.render(<Test />
, document.getElementById('components-enter-animation-demo-page'));

页面的进场和离场。

var ReactRouter = require('react-router');
var Router = ReactRouter.Router;
var Route = ReactRouter.Route;
var Link = ReactRouter.Link;
var EnterAnimation = antd.EnterAnimation;
var Menu = antd.Menu;

var App = React.createClass({
  getInitialState: function () {
    return {};
  },
  clickPage() {
    this.setState({
      enter: {delay: 0.3},
      leave: {delay: 0}
    });
  },
  render() {
    var key = this.props.location.pathname;
    return (
      <div>
        <Menu style={{marginBottom: 20}} mode="horizontal">
          <Menu.Item key='home'>
            <Link to="/" onClick={this.clickPage}>首页</Link>
          </Menu.Item>
          <Menu.Item key='page1'>
            <Link to="/page1" onClick={this.clickPage}>Page 1</Link>
          </Menu.Item>
          <Menu.Item key='page2'>
            <Link to="/page2" onClick={this.clickPage}>Page 2</Link>
          </Menu.Item>
        </Menu>
        <EnterAnimation className='demo-router-wap' enter={this.state.enter} leave={this.state.leave}>
            {React.cloneElement(this.props.children || <div key='home' className='demo-router-child'><h1>Home</h1><div>这是首页</div></div>, {key: key})}
        </EnterAnimation>
      </div>
    );
  }
});
var Page1 = React.createClass({
  render() {
    return (
      <div className="demo-router-child">
        <h1>Page 1</h1>
        <p><Link to="/page2">A link to page 2 should be active</Link>依次进场</p>
        <p><Link to="/page2">A link to page 2 should be active</Link>依次进场</p>
        <p><Link to="/page2">A link to page 2 should be active</Link>依次进场</p>
        <p><Link to="/page2">A link to page 2 should be active</Link>依次进场</p>
        <p><Link to="/page2">A link to page 2 should be active</Link>改变样式</p>
      </div>
    );
  }
});
var Page2 = React.createClass({
  render() {
    return (
      <div className="demo-router-child">
        <h1>Page 2</h1>
        <p><Link to="/page1">a link to page 1 </Link>我是页面2.</p>
        <p><Link to="/page1">a link to page 1 </Link>我是页面2.</p>
        <p><Link to="/page1">a link to page 1 </Link>我是页面2.</p>
        <p><Link to="/page1">a link to page 1 </Link>我是页面2.</p>
      </div>
    );
  }
});
React.render((
  <Router>
    <Route path="/" component={App} ignoreScrollBehavior>
      <Route path="page1" component={Page1} />
      <Route path="page2" component={Page2} />
    </Route>
  </Router>
), document.getElementById('components-enter-animation-demo-router'));

router 组合的进场与出场动画。