Jump to content
GreenSock

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

GSAP and React is it possible to pass a dynamic reference URL to a clipPath?

Recommended Posts

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.

Share this post


Link to post
Share on other sites

Hi Gilbert,

 

I'll assume that the clipPathId passed in the components props is the url you want to add, right?

 

If that's the case you can use template literals a feature from ES2015:

 

<g ref={(el) => { this.clipPathReveal = el; }} clipPath={`url#${this.props.clipPathId}`}>

 

If this is not what you're after, please let us know how the specific clip url is being passed.

 

Happy Tweening!!!

  • Like 2

Share this post


Link to post
Share on other sites

Hi Rodrigo,

 

Thanks. That didn't work, but this did work:

<g ref={(el) => { this.clipPathReveal = el; }} clipPath={`url(#${this.props.clipPathId})`}>

 

Your suggestion showed me the way :)

  • Like 1

Share this post


Link to post
Share on other sites

Ahh yeah the parenthesis, sorry SVG is not my thing.

 

Unlucky you @PointC didn't answer this question :D:D, but glad to hear you were able to solve it

 

Happy Tweening!!!

  • Like 1
  • Haha 1

Share this post


Link to post
Share on other sites
25 minutes ago, Rodrigo said:

Unlucky you @PointC didn't answer this question :D:D, but glad to hear you were able to solve it

 

My apologies. When I see React in the thread title I just assume the Rodrigo React Signal has been fired up and my services will not be necessary.

 

kkesqWD.jpg

  • Like 2
  • Haha 4

Share this post


Link to post
Share on other sites
13 hours ago, PointC said:

My apologies. When I see React in the thread title I just assume the Rodrigo React Signal has been fired up and my services will not be necessary.

 

The signal is only visible at night, so it might be awhile before he actually sees it.

 

Maybe you should fill that void. I hereby promote you to the role of Senior Daytime React Answering Manager, so you should start learning it. I think the basics are pretty easy to pickup, and being able to combine JavaScript with HTML/SVG is a joy.

https://reactjs.org/

https://reactjs.org/tutorial/tutorial.html

 

 

 

  • Like 6

Share this post


Link to post
Share on other sites
19 minutes ago, OSUblake said:

Maybe you should fill that void. I hereby promote you to the role of Senior Daytime React Answering Manager, so you should start learning it.

 

Sounds good. It's officially item 1,437 on my 'to-do' list so I may not get to it until the year 2029.

 

Unless you're gonna let me use your Blaketrix headjack so I can learn it in a few seconds. 

 

r0RjYUz.jpg

  • Like 3
  • Haha 3

Share this post


Link to post
Share on other sites
18 hours ago, PointC said:

 

Sounds good. It's officially item 1,437 on my 'to-do' list so I may not get to it until the year 2029.

 

Unless you're gonna let me use your Blaketrix headjack so I can learn it in a few seconds. 

 

r0RjYUz.jpg

 

I feel you pain bruv!

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×