Search code examples
javascriptreactjsanimationgsap

Pause GSAP animation after 2nd react component rendered


Trying to pause or remove GSAP animation within the else part of this conditional..

Container code -

     renderNews = () => {
  /**
   * Renders news snippets, no filtering at this time
   */
    let max = 2
    let count = 0
    let posts = this.props.posts.map((article) => {
      count++
      console.log('count' + count)
      console.log('renderNews article => ', article)
      if (count <= max) {
        return (
          <Grid md={0.5} sm={1} key={article.id} >
            <SnippetNewsEvents
              image={article.featured_media}
              event={false}
              title={article.title.rendered}
              date={moment(article.date_gmt).format('Do MMMM YYYY')}
              excerpt={article.excerpt.rendered}
              buttonText='Read More'
              link={'/posts/' + article.slug}
            />
          </Grid>
        )
      } else {
        return ( // or whatever the right grid thing is
          <Grid md={1 / 3} sm={1 / 2} xs={1} key={article.id} >
            <SnippetNewsEvents
              //innerRef={null}
              image={article.featured_media}
              title={article.title.rendered}
              date={moment(article.date_gmt).format('Do MMMM YYYY')}
              //  excerpt={article.excerpt.rendered}
              buttonText='Read More'
              link={'/posts/' + article.slug}
            />
          </Grid>
      )
      }
    })
    return posts
  }

Component Code -

export default class SnippetNewsEvents extends React.Component { // eslint-disable-line react/prefer-stateless-function
  constructor () {
    super()
    this.state = {
      image: null
    }
  }
  componentDidMount = () => {
    this.getImage(this.props.image)
    this.contentTween = new TimelineMax().add([
      TweenMax.fromTo(this.wrapper, 1, {
        scale: '0.95'
      }, {
        scale: '1'
      })])

    this.scene = new ScrollMagic.Scene({triggerElement: this.wrapper, triggerHook: 0.8, duration: window.innerHeight/2})
                  .setTween(this.contentTween)
                  .addIndicators({name: 'snippets'})
                  .addTo(scrollController)
  }
  getImage (image) {
    if (typeof image === 'string') {
      this.setState({image: image})
    } else if (typeof image === 'number' && image !== 0) {
      fetch('http://hkserverdev.weruinit.com/wp-json/wp/v2/media/' + image)
      .then(response => response.json())
      .then(data => {
        this.setState({image: data.source_url})
      }).catch(error => {
        if (dev) console.error('Error:', error)
      })
    }
  }
  showImage (image) {
    if (this.state.image == null) {
      return null
    } else {
      return (
        <SnippetImage src={this.state.image} data-rjs='2' />
      )
    }
  }
  showLocation = () => {
    if (this.props.event) {
      return (
        <EventsDetailWrapper>
          <H3c title={this.props.title}>{this.props.title}</H3c>
          <EventsTimeLocation>
            <Combo>
              <Icon className='buttonIcon' src={require('../../images/time_icon.png')} data-rjs='2' />
              <Detail copy={this.props.date} news />
            </Combo>
            <Combo>
              <Icon className='buttonIcon' src={require('../../images/location_icon.png')} />
              <Detail copy={this.props.location} />
            </Combo>
          </EventsTimeLocation>
        </EventsDetailWrapper>
      )
    } else {
      return (
        <NewsDetailWrapper>
          <Detail uppercase={this.props.event} copy={this.props.date} />
          <H3c>{this.props.title}</H3c>
          <Detail excerpt copy={this.props.excerpt} />
        </NewsDetailWrapper>
      )
    }
  }
  componentWillUnmount () {
    this.scene = this.scene.destroy()
  }
  render (props) {
    if (dev) console.log('SnippetNewsEvents => ', this.props)
    return (
      <EventsItemWrapper innerRef={c => (this.wrapper = c)} className='snippet' small={this.props.compressed}>
        {this.showImage(this.props.image)}
        {this.showLocation(this.props.event)}
        <Button className='hvr-trim hvr-trim-alt' black snippet link={this.props.link} content='Read More'>{this.props.content}</Button>
      </EventsItemWrapper>
    )
  }
}

I'm new to both react and GSAP and js :((


Solution

  • Given that you've defined this.scene in SnippetNewsEvents, you can use a ref to stop the animation.

    You should turn renderNews into a class component and then use its lifecycle method componentWillReceiveProps to either stop or start the animation. Let's see how this might be implemented:

    container component
    
    ...
    
    componentWillReceiveProps(nextProps) {
     nextProps.posts.map((article) => count++ ...));
     // condition is met, stop animation
     if (count > max) { this.snippetNewEventsRef.contentScene.pause(); return; }
    }
    
    render() {
      return (...<SnippetNewsEvents ref={(c) => this.snippetNewsEventsRef = c} .../>);
    }
    

    This is off the top of my head though, so test it first. It should work: in this case, this.snippetNewsEventsRef is an object that will have a key contentTween.

    Edit: tested, working. See JSBin here