React中常见的动画实现的几种方式(5)

CSSTransitionGroup 实现动画的优点是:

  1. 简单易用,可以方便快捷地实现元素的入场和离场动画;
  2. 与 React 结合,性能比较好。

CSSTransitionGroup 缺点也十分明显:

  1. 局限于出现动画,入场动画和离场动画;
  2. 由于需要制定 transitionName ,灵活性不够;
  3. 只能依靠 css 实现简单的动画。

四、结合 hook 实现复杂动画

在实际项目中,可能需要一些更炫酷的动画效果,这些效果仅依赖于 css3 往往较难实现。此时,我们不妨借助一些成熟的第三方库,如 jQuery 或 GASP,结合 React 组件中的生命周期钩子方法 hook 函数,实现复杂动画效果。除了 React 组件正常的生命周期外, CSSTransitionGroup 的底层 api TransitonGroup 还为其子元素额外提供了一系列特殊的生命周期 hook 函数,在这些 hook 函数中结合第三方动画库可以实现丰富的入场、离场动画效果。

TransisitonGroup 分别提供一下六个生命周期 hook 函数:

  1. componentWillAppear(callback)
  2. componentDidAppear()
  3. componentWillEnter(callback)
  4. componentDidEnter()
  5. componentWillLeave(callback)
  6. componentDidLeave()

它们的触发时机如图所示:

示例

GASP 是一个 flash 时代发展至今的动画库,借鉴视频帧的概念,特别适合做长时间的序列动画效果。本文中,我们用 TransitonGroupreact-gsap-enhancer (一个可以将 GSAP 应用于 React 的增强库)完成一个图片画廊,代码如下:

import React, { Component } from 'react'; 
import { TransitionGroup } from 'react-transition-group'; 
import GSAP from 'react-gsap-enhancer' 
import { TimelineMax, Back, Sine } from 'gsap';

class Photo extends Component { 
  constructor(props) {
    super(props);
  }

  componentWillEnter(callback) {
    this.addAnimation(this.enterAnim, {callback: callback})
  }

  componentWillLeave(callback) {
    this.addAnimation(this.leaveAnim, {callback: callback})
  }

  enterAnim = (utils) => {
    const { id } = this.props;
    return new TimelineMax()
      .from(utils.target, 1, {
        x: `+=${( 4 - id ) * 60}px`,
        autoAlpha: 0,
        onComplete: utils.options.callback,
      }, id * 0.7);
  }

  leaveAnim = (utils) => {
    const { id } = this.props;
    return new TimelineMax()
      .to(utils.target, 0.5, {
        scale: 0,
        ease: Sine.easeOut,
        onComplete: utils.options.callback,
      }, (4 - id) * 0.7);
  }

  render() {
    const { url } = this.props;
    return (
      <div className="photo">
        <img src={url} />
      </div>
    )
  }
}

const WrappedPhoto = GSAP()(Photo);

export default class Gallery extends Component { 
  constructor(props) {
    super(props);
    this.state = {
      show: false,
      photos: [{
        id: 1,
        url: 'http://img4.imgtn.bdimg.com/it/u=1032683424,3204785822&fm=214&gp=0.jpg'
      }, {
        id: 2,
        url: 'http://imgtu.5011.net/uploads/content/20170323/7488001490262119.jpg'
      }, {
        id: 3,
        url: 'http://tupian.enterdesk.com/2014/lxy/2014/12/03/18/10.jpg'
      }, {
        id: 4,
        url: 'http://img4.imgtn.bdimg.com/it/u=360498760,1598118672&fm=27&gp=0.jpg'
      }]
    };
  }

  toggle = () => {
    this.setState({
      show: !this.state.show
    })
  }

  render() {
    const { show, photos } = this.state;

    const renderPhotos = () => {
      return photos.map((item, index) => {
        return <WrappedPhoto id={item.id} url={item.url} key={`photo${item.id}`} />;
      })
    }

    return (
      <div>
        <button onClick={this.toggle}>toggle</button>
        <TransitionGroup component="div">
          {show && renderPhotos()}
        </TransitionGroup>
      </div>
    );
  }
}
      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/270.html