Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...

Gilbert

Members
  • Posts

    4
  • Joined

  • Last visited

Posts posted by Gilbert

  1. I am trying to use GSAP with React. 

    In React I am creating a component with some text animations,  for which I would I would like to create several instances at runtime.

     

    The main component should look like this:

    import React, { Component } from 'react';
    import './App.css';
    import { TimelineMax, Bounce} from 'gsap';
    
    import Title from './Title.js';
    
    let mainTimeline;
    
    class App extends Component {
      componentDidMount() {
        setTimeout(this.animate, 1000);
      }
    
      componentWillUnmount() {
        mainTimeline.kill();
      }
    
      animate = () => {
        mainTimeline = new TimelineMax({ id: 'Everything' });
        const titleTimeLine = new TimelineMax({ id: 'Title' });
        const titleTimeLine2 = new TimelineMax({ id: 'Title2' });
    
        mainTimeline.addLabel('start');
    
        // get external timelines
        titleTimeLine.add(this.title.timelineEnter);
        titleTimeLine2.add(this.title2.timelineEnter)
    
        mainTimeline
          .add(titleTimeLine, 'start')
          .addLabel("title2")
          .add(titleTimeLine2, 'title2')
      }
    
      render() {
        return (
          <div className="App">
            <Title text="The benefits are:" clipPathId="clipPath1" ref={(el) => { this.title = el; }}/>
            <Title text="This should work" clipPathId="clipPath2" ref={(el) => { this.title2 = el; }}/>
          </div>
        );
      }
    }
    
    export default App;
    
    
    

    And the Tile component is:

    import React, { Component } from 'react';
    import { TimelineMax, Power4, SlowMo} from 'gsap';
    import './Title.css'
    
    class Title extends Component {
      constructor(props) {
        super(props);
        const { text, clipPathId } = this.props;
      }
    
      get timelineEnter() {
        const tl = new TimelineMax();
        const duration = 1;
    
        tl.to(this.line, duration, {attr:{x1:120, x2:880}, ease:Power4.easeInOut})
        .to([this.reveal, this.line], duration, {y:"+=120",  ease:Power4.easeInOut})
        .to(this.line, duration, {attr:{x1:500, x2:500}, ease:Power4.easeInOut})
        .to(this.clipPathReveal, duration, {y: -180, scale: .3, transformOrigin:"50% 50%", ease:SlowMo.ease.config(0.7, 0.7, false)})
      return tl;
    }
    
    render() {
      return (
        <svg className="demo" viewBox="0 0 1000 500">
          <defs>
            <clipPath id={this.props.clipPathId} ref={(el) => { this.theClipPath = el; }}>
              <rect ref={(el) => { this.reveal = el; }} x="0" y="-100" width="1000" height="250" fill="#000" />
            </clipPath>
          </defs>
          <line ref={(el) => { this.line = el; }} x1="500" y1="150" x2="500" y2="150" strokeWidth="20" stroke="red"/>
          <g ref={(el) => { this.clipPathReveal = el; }} clipPath="url(#clipPath1)">
            <text transform="translate(500 250)" fill="#3088Ef" textAnchor="middle" fontSize="80">{this.props.text}</text>
          </g>
        </svg>
        );
      }
    }
    
    export default Title;

    The problem is that in the code:
     

    <g ref={(el) => { this.clipPathReveal = el; }} clipPath="url(#clipPath1)">
        <text transform="translate(500 250)" fill="#3088Ef" textAnchor="middle" fontSize="80">{this.props.text}</text>
    </g>

    for the clipPath attribute, I need to pass a dynamic URL. Otherwise, it doesn't work correctly.

     

    Is there a way to pass a dynamic id to the URL in clipPath="url(#clipPath1)".

    Something like clipPath="url({dynamicURL})" or something?

     

    In the first instance of <Title>, it should produce clipPath="url(#clipPath1)", while in the second it should be clipPath="url(#clipPath2)" and so on.

  2. I am experimenting with these title animations https://github.com/bigfanjs/react-titles and I want to sequence some titles. 

    The questions that I have are:

     

    How can I pause or play the original animations?

    How can I sequence the animations (for each title)? - For example, play the first one, wait for .7 seconds and play the second one, etc.

    How can I set the initial position of each title?

     

    My code is:

    Here is the code I have:

    import React, { Component, Fragment } from "react";
    import styled from "styled-components";
    import * as titles from "react-titles";
    import { TimelineMax, Power3 } from "gsap";
    
    const mytitles = [
      {
        component: "Title2",
        title: "This is ",
        subTitle: "Sweet",
        isOpen: false,
        size: 100,
        x: '50'
      },
      {
        component: "Title6",
        title: "Let' see",
        subTitle: "if this works",
        isOpen: false,
        size: 400,
        x: '400'
      },
    ]
    
    class Title extends Component {
      constructor(){
            super();
            this.renderTitle = this.renderTitle.bind(this);
            this.restartHandler = this.restartHandler.bind(this);
            this.tl = new TimelineMax({paused: true});
        }
    
      state = {
        isOpen: false
      }
    
      restartHandler(){
            const {tl} = this;
            tl.reversed( !tl.reversed() );
        }
    
      componentDidMount(){
            const {tl} = this;
    
            mytitles.forEach( (e,i) => {
                //tl.set(this.refs[e.component], {left:e.x, top:e.x})
                tl.to( this.refs[e.component], 1, {x: e.size, y: e.size/3 , scale: 0.5, opacity: 0.5}, .5 * i );
            });
            tl.reverse();
        }
    
      getComponent(e) {
        const ATitle = titles[e.component];
        //ATitle.handleRest();
    
        //const {t1} = this;
        //this.tl.set(this.refs[e.component], {left:e.x, top:e.x})
        return(
          <div  className="box" key={e.component} ref={e.component} >
            <ATitle
              size={e.size}
              text1={e.title}
              text2={e.subTitle}
              open="false"
              style={{ position: "absolute", x: " +e.x+" , y: " +e.x+", "fill": "orange" }}
              onComplete={this.handleComplete}
            />
          </div>
        )
      }
    
      renderTitle(e,i){
            return(
                this.getComponent(e)
            );
        }
    
    handleComplete = (status) => {
        /*const {selected, component} = this.state;
    
        if (!status && selected !== component) {
          this.setState({ component: selected, isOpen: true });
        }*/
      }
    
      render() {
        return(
            <div>
                <button onClick={this.restartHandler}>Toggle Tween</button>
                <div>
                    {mytitles.map(this.renderTitle)}
                </div>
             </div>
       )
      }
    }
    
    export default Title;

     

×