Jump to content

Rodrigo last won the day on March 17 2019

Rodrigo had the most liked content!


  • Posts

  • Joined

  • Last visited

  • Days Won


Rodrigo last won the day on March 17 2019

Rodrigo had the most liked content!


2,662 Superhero

About Rodrigo

Profile Information

  • Gender
  • Location
    Santiago - Chile

Contact Methods

  • Skype

Recent Profile Visitors

22,891 profile views
  1. Hi, As mentioned before I haven't had time to dig deeply into the Hooks API and all I can offer right now is a simple example but no real explanation on how it actually works, sorry about that. Here is a live sample using a Timeline instance with React hooks: https://stackblitz.com/edit/gsap-react-hooks-timeline-instance-toggle As you can see it uses a useEffect at first run in order to create the timeline and then you can add all the child instances you want to the timeline. Unfortunately this doesn't works: let tweenTarget = null; const tl = new TimelineLite({paused: true}); useEffect(() => { tl .to(tweenTarget, 0.5, {x: 100}) .to(tweenTarget, 0.5, {y: 100}) .to(tweenTarget, 1, {rotation: 360}) .reverse(); }, []); useEffect(() => { tl.reversed(!toggle); }, [toggle]); Even though in the useEffect callback triggered by the toggle update, tl is defined and it's reversed state is updated, nothing happens. This is the part I can't give you a proper explanation about. For the foreseeable future just work with the timeline in the initial useState and then in the useEffect add the instances, like in the live sample. As soon as I have an official explanation about this, I'll post it here and in the other threads dealing with hooks. Happy Tweening!!!
  2. @SENPAI & @xraymutation, This is trickier than one can expect because instead of using RTG to animate the transition between route components, the idea is to animate in a full page overlay, change the rendered component based on the new route and then animate the overlay out. Normally in RTG you pass the component that matches the target route which is animated. One solution I can think of is to play with the entering and exiting API's from RTG in order to animate just the overlay and produce the route change using a set instance in the addEndListener in order to have everything working with GSAP's timing. Of course this is easier said than done. Hopefully during the weekend I'll have some time to check this, but I can't make any promises since I'm extremely tight right now time-wise. An alternative is to create an animation in the overlay and use react router's API to make the route changes using GSAP callbacks. The trade-off in this approach is that you loose the capacity of animating the route changes using the browser's forward and back buttons, in those cases the routes change without any animation. Let me know which approach you prefer and perhaps we can work out something together. Happy Tweening!!!
  3. On top of Zach's great advice, try to avoid using regular selectors and use $refs instead: https://vuejs.org/v2/api/#ref
  4. @danboyle8637 I made a scroll spy for a React app a while ago based on this repo: https://github.com/makotot/react-scrollspy. It is quite experimental and rudimentary, If you want I can look around to find it and give it to you so you can check it. The principle is quite simple, the code listens to the scroll event (I know is not the best way) of a main wrapper and compares the scroll top value with the position of the elements that you want to animate or in the use case of that particular project set the active menu item. When the scroll position exceeds the top position of an element and if the current element is different from the value stored in the state, it updates a visible property in the state. Like that the state is updated only once per element and not on every scroll update. Is not the most efficient way but is far more efficient than constantly updating the state on every scroll event.
  5. Honestly I'm out of my element with the intersection observer API here so I won't be able to help you with that, sorry The one thing that gets my attention is the fact that the animation's target is the same element. If we're not talking about a dynamic element why not create the animation in the same component and trigger it with the intersection observer (if that is even possible). By playing a bit with your code and adding some callbacks I can see that the animation is actually starting, updating and completing, so the issue lays on the DOM node passed to it not being affected by the GSAP instance which is odd. Unfortunately the only advice I can give you is try to create your animation inside the component and just control that instance instead of creating it over and over again and use that in the component's hook.
  6. Honestly I haven't played with the intersection observer API at all. By doing some quick reading on the subject I don't see any issue as long as you're careful about passing an actual DOM node to the function that creates the GSAP instance. IMHO I don't see any big issue on keeping the code that creates the GSAP instances inside the components unless is exactly the same code for a bunch of different components, and I mean that in the DRY-way (Don't Repeat Yourself), ie, if you don't want to write the same code over and over again. Regarding the kill feature, this is not like a biological kill in terms that the GSAP instance ceases to exist, basically the instance is stopped and you can be sure that is not moving in any direction and that anything related to it will be executed until is explicitly set in that way. If you want to completely remove the instance you can reset it's reference in memory with null. The only check I can think of is the isActive() method, that should return false if the GSAP instance was killed. Finally the GSAP instance should be killed even though is instantiated in a different file because the DOM node will have a reference to the instance's position in memory, this does not depends of the context where the animation is actually created, which is exclusive of the code block where it happens. Also keep in mind that this will eventually happen in the same file but in a specific closure of the bundled file between lines X and Y. Happy Tweening!!
  7. Ha!!! is already complicated enough, so no thanks!!!
  8. I could tell you, but after I'd have to kill you... Absolutely is a matter of having the time to create the samples and update the guide as well. Is definitely in my to-do list:
  9. Hi and welcome to the GreenSock forums. Sorry to hear that you're experiencing problems with GSAP. Unfortunately it seems to be an issue with some CORS issue accessing bundlephobia.com's API, so the live sample is not working, for me at least. In this post is discussed how to create and toggle animations using the Hooks API: Also you can check a live simple example here as well: https://stackblitz.com/edit/gsap-react-hooks-toggle For I can see in your code you're using two different timelines to affect the same elements into different values. Ideally try to create a GSAP instance that you can toggle for each sub-menu element. Also you're adding new instances to the timeline every time the component is updated, so try to add an empty array when creating the GSAP instances so that code runs only when the component is mounted and toggle the animations using another useEffect call only when the open state property is updated. Hopefully this can help you as you try to get a working live sample so we can take a better look at it. Happy tweening!!
  10. Hi, you can create the split text as a property in the component's class, in the constructor: constructor (props) { super(props); this.title = null; this.titleChars = null; } Here this.title should point to a ref in the render method Then in the component did mount method you can create the SplitText instance and assign the chars to the property created in the constructor: componentDidMount () { const mySplit = new SplitText(this.title, { type: "words, chars", position: "absolute" }); this.titleChars = mySplit.chars; // array of DOM elements (<div> tags) TweenMax.staggerTo(this.titleChars, 1, {x: 10, y:-10, rotation: 180, autoAlpha: 0}, 0.1); } That is working for me, give it a try and let us know how it works. Happy tweening!!
  11. You could filter the visible elements and render just those using RTG, like in this sample: https://stackblitz.com/edit/gsap-react-simple-transition-group?file=simple-transition.js Of course that is just one element but is the same principle. When the show value in the state is toggled the element is animated in/out with the consequent mount/unmount. Instead of managing the show value on each component's you could pass it as a prop to each element. If you ask me I would use array.filter() to get a filtered version of the array elements that should be visible and render just those: https://stackblitz.com/edit/gsap-react-transition-group-list In that sample as soon as you remove an element, the array is reduced but the element is still rendered. As the animation-out is completed the element is removed from the App's tree. Take a look at both samples and hopefully you'll get a good grasp on how to tackle your situation. Finally you could take a look at this article by Addy Osmani: https://addyosmani.com/blog/react-window/ Happy Tweening!!
  12. You could use a mix of the code in these codepens: https://codepen.io/GreenSock/pen/zcmpo https://codepen.io/GreenSock/pen/uhKIy Happy Tweening!!!
  13. You're welcome. For styles I'm an old fashioned guy and use SASS in separate files. I just don't like styled components. There used to be this concept called "Separations of Concerns" which I still follow to this day. IMHO styles go with styles, pure JS goes with pure JS and React code goes with React code, but again that's just my and my two cents on the subject. If you use breakpoints for animations my advice would be to use the context API and the root component of your app to keep track of the screen size. Like that you can check the screen size when creating/running your animations on every component in the app without the need of passing props down the component tree. Of course if at some point you plan to implement redux you can use it as well to spread the screen size from a single component that listens to the window resize event. The jumpy behaviour could be related to sub-pixel rendering but if you're using x and y that shouldn't be an issue. Perhaps the content your animating is creating the issue, maybe large images with transparency or shadows. Those things normally cause a lot of stress on the rendering engine. This is just on safari? Chrome, Firefox, Edge work OK? Happy Tweening!!
  14. Ahh yes my bad. I meant a Draggable trigger: https://greensock.com/docs/Utilities/Draggable Scroll down a bit in the features and you'll find it. Also here is a simple example: https://codepen.io/rhernando/pen/IiHgq Happy Tweening!!
  15. Hi and welcome to the GreenSock forums. Honestly I don't think using transition group is a good fit for the type of site you have in mind. Transition group fits better in cases you need to animate elements that will be mounted/unmounted in the React app, rather than regular animations. The best approach I can think of is to use either React's context API, redux/mobx or direct props to pass a method to all child components to add the particular timeline of each component to the master one. I would avoid doing this at all cost: // create react class class Box1 extends Component {} export default Box1; export const Timeline1 = () => {}; Mainly because there is no guarantee that the DOM element will be mounted when the file actually reaches the point of the function definition that creates and returns the timeline. Instead create the timeline inside the component (the react-way soto speak) and then use the method created in the parent component to send that animation and add it to the master timeline. Something like this: Parent Element class App extends Component { constructor (props) { super(props); this.masterTl = new TimelineMax({useFrames:true, paused:true}); this.addChildTimeline = this.addChildTimeline.bind(this); } // method to add child timelines to the master addChildTimeline (childTl, position) { this.masterTl.add(childTl, position); } render() { return <div> <Box1 addChild={this.addChildTimeline} /> </div>; } Child Component class Box1 extends Component { constructor (props) { super(props); this.box1 = null; this.tl = new TimelineLite({useFrames:true, paused:false}); } componentDidMount() { this.tl .to(this.box1, 200, { opacity: 1, }) // here you'll have to find a way to plug this duration value .to('.box-1', duration*2, { scale: 2.5, top: "80%", left: '-30%', }, "-=200"); this.props.addChild(this.tl, "+=200"); } render () { return <div> <div ref={div => this.box1 = div}> // box1 content here </div> </div>; } As you can see transition group is not needed at all and for this setup it will only make things more complicated. Unfortunately I don't have time right now and for the foreseeable future to create a concrete sample of this, so I hope that this simple advice is enough to get you started. Happy Tweening!!