chenglou / react-motion

A spring that solves your animation problems.
MIT License
21.69k stars 1.16k forks source link

Removing styles after transition completes #293

Open Ahrengot opened 8 years ago

Ahrengot commented 8 years ago

I'm using react motion for view transitions and I'm running into problems where the styling needed for my transitions (a mix of transform and opacity) interferes with my child component styling and after the transitions there's really no use for the transitions styles anyway, so I would like to remove them after the animation has completed.

Is there a good pattern for that currently? Something simmilar to [clearprops](http://greensock.com/docs/#/HTML5/GSAP/Plugins/CSSPlugin/) in GSAP would be ideal. Is it possible?

nkbt commented 8 years ago

I guess you need to use onRest() and pass empty style object to your styled component instead of one with animated styles

dozoisch commented 8 years ago

@nkbt it seems like onRest is only available on Motion and not TransitionMotion. Do you have any idea how that would be doable in that case? Or is it missing a pr to add the same functionality to TransitionMotion :)?

jagreene commented 8 years ago

:+1: I would also love to see onRest() available in TransitionMotion

jain-akash commented 8 years ago

I also need onRest() in TransitionMotion. It would be good if we can get onRest for when each of the individual element rests

guncha commented 8 years ago

There is a bit of a deeper issue at the core of which is the fact that the callback has no idea if the elements are entering, leaving or being rendered with their final styles. My problem right now is that I'm trying to add a position: "absolute" on a panel that's being faded out and there isn't a clean way to do it. It could be worked around using onRest, but I think a cleaner solution would be to add a key to the {key, data, style} object that tells us if the element is transitioning. I.e.:

<TransitionMotion styles={ this.panels() }
  willEnter={ this.willEnter }
  willLeave={ this.willLeave }
  children={ panels =>
    <div>{
      panels.map(panel => {
        let position = panel.entering || panel.leaving ? "absolute" : "relative"
        return <div style={ merge({position}, panel.style) } children={ panel.data } />
      })
    }</div>
} />

This would enable adding transition-only styles and remove them when they're no longer needed.

otmjka commented 8 years ago

There is an idea/hack to use indication component for onRest leaving animation:

class Hack extends Component{
  componentWillUnmount(){
    console.log('end animation');
  }

  render(){
    return (<div>Hack</div>);
  }
}

class FullPageTransition extends Component{

  static PropTypes = {
    dir: PropTypes.number.isRequired,
    animItems: PropTypes.array.isRequired,
    onWheelHandler: PropTypes.func.isRequired,
  };

  static defaultProps = {
    animItems: EMPTY_ARR,
  };

  // Motion
  willEnter() {
    return {
      transform: 0,
      opacity: 0,
    };
  }

  willLeave() {
    return {
      transform: spring(100, PRESET_WL),
      opacity: 1,
    };
  }

  getStyles() {  
    const {animItems} = this.props;
    return animItems.map((item)=>{
      return {
        key: item.key, 
        style: {transform: spring(0), opacity: spring(1) },
        data: item,
      };
    });
  }

  @autobind
  renderItem(config, i, list) {
    const inc = list.length - i;

    const {dir, onWheelHandler} = this.props;

    const props = {
      key: config.key,
      style: {
        ...STYLES.container, 
        background: config.data.background, 
        zIndex: 101 + inc,
        opacity: config.style.opacity,
        transform:`translate3d(0,
          ${dir * config.style.transform}%, 0)`
      },
      onWheel: onWheelHandler
    };
    return (
      <div {...props}>

        {config.key} {config.style.transform}
        <Hack />
      </div>);
  }

  renderItems = (interpolatedStyles) => {
    return (
      <div className="asdasdasd">
        {interpolatedStyles.map(this.renderItem)}
      </div>
    );
  };

  render(){
    return (
      <TransitionMotion
        willEnter={this.willEnter}
        willLeave={this.willLeave}
        styles={this.getStyles()}>

        {this.renderItems}
      </TransitionMotion>
    );
  }
}
oliverox commented 7 years ago

I need the onRest() callback to be available with StaggeredMotion. Any plans on when this would be available? Or is there any way to make it happen now?

mattvague commented 7 years ago

@oliverox I haven't found a way but I also need this

ollwenjones commented 6 years ago

PR for adding a simple onRest to TransitionMotion #552