Rodrigo last won the day on July 26 2016

Rodrigo had the most liked content!

Rodrigo

Moderators
  • Content count

    1,552
  • Joined

  • Last visited

  • Days Won

    148

Rodrigo last won the day on July 26 2016

Rodrigo had the most liked content!

Community Reputation

1,844 Superhero

2 Followers

About Rodrigo

  • Rank
    Advanced Member

Contact Methods

  • Skype
    r_hernando

Profile Information

  • Gender
    Male
  • Location
    Santiago - Chile

Recent Profile Visitors

19,105 profile views
  1. React and GSAP

    @axe-z I haven't played too much with React 16 and GSAP yet but it seems that it hasn't change that much. With that in mind this samples use React 15, Transition group 2.2.0 (latest is 2.2.1) and React Router 4.1.2 (latest 4.2.0) so they should come in handy in order to get you started. Simple component transition using GSAP https://codesandbox.io/s/yvYE9NNW Using React Router to animate the mounting and unmounting of the components: https://codesandbox.io/s/mQy3mMznn Happy Tweening!!
  2. Using TimelineLite with React and Child Components

    Hi, The thing is that the `onComplete` callback is being used to mount/unmount the component from the App and the DOM. He's using React Transition Group, which is heavily inspired from Angular's ng-animate (at least the old version of ng-animate when you had to pass a callback to onComplete in order to keep track of things), and honestly my personal opinion is that for a simple mount/unmount toggle He's over-complicating things, because I don't think is absolutely necessary to use the component's lifecycle methods in the animations, react transition group does that for you, but everyone has it's own ways so if it's working for Him, that's great!!. Here are two samples of using GSAP with React and Transition Group. This is a simple component toggle, the component gets animated and when the out animation is complete it's unmounted, when the in animation starts is mounted: https://codesandbox.io/s/yvYE9NNW As you can see the `<Transition>` element is just a high order component that adds some features to the regular component using the `addEndListener` attribute. This sample is a todo list using the same set up. Never mind the code that's commented out, I keep that in case someone needs to use... [sigh] CSS transitions (sorry for using the forbidden language in the forums :D): https://codesandbox.io/s/7Lp1Q8WBA Hope this helps. Happy Tweening!!!
  3. GSAP and react

    @Carl, @PointC, you guys always know how to put a smile in my face. Is great to feel welcome everytime I pop in the forums. @thomas159, since you want to do a one time stagger the best choice (that I can think of at least) would be to create a timeline in the `componentDidMount` method and add each instance looping through the same array used to add the elements in the DOM. The only caveat is that you need a reusable property in each element of the array for the reference, which in the case of your sample could be the name property of each element. Here's a very simple example: Happy Tweening!!
  4. GSAP and react

    If you're using an array with the data you'll use as a reference, then there's no need to use an anonymous function in the ref attribute, just pass the property of the element being used in the map helper: const data = [ {id:1, name: 'box1'}, {id:2, name:'box2'} ] data.map( (item, index) => className={styles.box} key={`box${index}`} ref={item.name}; ); Then reference the element following the same pattern: tl.to(this.refs.box1, 0.5, { backgroundColor:"#F19939" }); Keep in mind that the GSAP instance must be created inside the component's that has the node element. Here's a simple example made in codepen. Is not a lot of code so it should be easy to follow: Happy tweening!!
  5. GSAP and react

    Hi, Basically the ref attribute in React, points to the node element being created and then added to the DOM. When you use a function in the ref attribute, the parameter passed by react is the DOM node being created. Now the problem with that code when used in a map array helper, is that is adding a reference to that specific node in the react component. So every time the map helper runs the reference to this.name is updated to that last element. Therefore when the array mapping is complete, the reference in the component is only the last element. render(){ return( '<div ref={ (node)=>{console.log(node)} }> </div>' ); } //the console will return the <div></div> tag This is perhaps one of the sore spots of animating mapped collections with react, how can we reference all the elements created in the map helper. The main question here is, what type of animation you're trying to create?. If you want to do a one time stagger, then perhaps you could create an array and use the map callback in order to push each node element and do the tagger. If you want to access each element independently, then you should give a unique name to each one in the ref in order to reach them when necessary. Right now I'd suggest that you post back with the type of animation you need and we can take it from there. Best, Rodrigo.
  6. Accordion with dynamic height according to content inside

    Hi, This is a very simple concept I made some time ago for a wordpress site: The main thing to keep in mind is to kill any existing tween and create new ones after getting the new height of the element after the resize event. Is worth noticing that the animations are reeeeeeaaaally slow in order to test the code responsiveness, but you could use any GSAP instance you want. Also it could use some work in order to avoid looping through all the elements and do it just for the active ones. Is not precisely what you're doing but hopefully will help you get started. Happy tweening!!
  7. Photo Cube Animation

    Hi Anthony, Looks nice!!! Perhaps this could be useful to tween the timescale back to 0 when hovering over the cube and using an onComplete callback to snap the cube to the current face:
  8. Photo Cube Animation

    Hey Anthony, the delayed call was just a sample of using GSAP and modifying other state properties while the animation (delayed call) is working, nothing more. I agree with you that it has no use in your App . I also agree that using the react gsap enhancer shouldn't offer any upside in this particular scenario. As for configuring eslint globals, why don't you declare them in the .eslintrc.json file? { "env": {}, "parserOptions": {}, "globals": { "PIXI": true, "TweenLite": true, "TweenMax": true, "TimelineLite": true, "TimelineMax": true, "Elastic": true, "stripes": true, "axios":true }, "rules": {} } I always use that when working with eslint. Happy Tweening!!
  9. Photo Cube Animation

    Sweet demo Anthony!!! always good to see you coming back with awesome stuff!! For performance I would try to avoid using the elastic easing on all the thumbnails when clicking on the expanded image, I would go with a regular easeOut function, perhaps Power2 and use the elastic on the expanded being scaled down. For using react create app, I can't help you. I've baked my own start packages for working with react, angular, vue, etc. so I never use those tools. Also I've never been a big fan of this bundling madness that has taken over front end development, so even today sometimes I keep GSAP outside the bundled files. This is particularly useful when you end up with a bundled file over 1MB because you can create a pre-loader with GSAP. I'm sure Blake can give you some pointers in this regard. I see you're using timescale to speed up/down the animation using the pointer position. But also I saw this: TweenMax.to(this.timeline, currentFace.progressRemaining / 2, { time: this.timeline.getLabelTime(currentFace.id.toString()), ease: 'Back.easeOut', }); Why don't you create one TweenMax instance to rotate to each side, just like the one you already have, using relative values and a repeat:-1 with linearEaseNone in order to create an endless loop, or you can use the modifiers plugin as well, and based on the pointer position update the timescale between 0 and 1 like that you avoid code like the one above and keep it more simple. You can even put those GSAP instances in your component's state or even a redux store and just reference them. Finally I don't know how the GSAP instances could be messing with the App's state. As a rule of thumb, I try to avoid GSAP updating any property of the app's state that could mean a re-rendering that ultimately will affect the instance. If the GSAP instance will update something in the state, is vital that nothing else does because GSAP won't know about that and will keep going with the stored values, unless you reset and create the instance again. For example if a Tween is changing the X position of an object and is not entirely necessary to store that value in the state then don't, in order to avoid something that could mess that up. In your sample I can't see if the GSAP instance is updating anything from the state, so I'd need for you to tell me that. This is very simple examples of some things I made with react some time ago: In this basically GSAP just animates the DOM element and doesn't even know about the app's state. This is using a delayed call and the Tween updates a specific part of the state that nothing else can update. Finally with the button you can change another state property. Finally this is using the modifiers plugin: Hope that this helps. Best, Rodrigo.
  10. MonkeyPatching Tweens/Timelines for automated testing

    Yep, as I said I'm not convinced that my answer is what the issue is about. just never did a lot of unit test or end-to-end on gsap instances and the end values of the properties they affect, mostly checked that the instance was created by checking some specific properties. Also I haven't done a lot of testing on virtual DOM, mostly browser or Node, so I was attracted to the thread because of that. I've never used a lot of testing on the values because of my blind faith in GSAP, I just create the instances and I know that id something is not working is because I blew it at some point. I posted that answer with the hope that the phrase:"Sometimes the simplest solution is the best solution" could become true in it I'll keep waiting on @UncommonDave's posts to see how it develops. Happy Tweening!!
  11. MonkeyPatching Tweens/Timelines for automated testing

    Hi, Couldn't help to pinch in with a simple suggestion, and perhaps I'm overlooking the real issue in question. If I am please correct me and excuse me for not understanding the conversation. Is the problem that you need to run the tweens in order to check for callbacks and the elements' position?. What I think I understand for your posts is that, your test suite is taking far too long by waiting for a, let's say 5 seconds tween to be completed to check that everything actually happened. If that's the case why don't you use either seek(), or progress(), or time() to advance your GSAP instances to the end and check the values and callbacks. All those methods suppress callbacks by default, but you can pass a second parameter to trigger the callbacks between the current and final positions. You can do that at runtime after defining your instances or even at a specific moment or event of your code: var t = TweenLite.to(e, 1, {x:100, onStart:startCallback, onComplete:completeCallback}); // then move the playhead to the end triggering all the callbacks t.progress(1, false); // using time t.time(t.duration(), false); // using seek t.seek(t.duration(), false); Again, sorry if I'm misunderstanding the problem, if so... sorry. Happy Tweening!!
  12. TimelineMax/attrPlugin not working with React

    Bingo!!!, that's the key to understand it. As always @OSUblake has the nail locked and He hits it in the head!!! @GreenSock, well, this is kind of tricky. First when working with React data is normally passed either as a JSON file or in object notation. So normally elements that share something in common (such as a specific class) are stored in arrays: const els = [ {name: "Jack", ocupation:"Master of GSAP"}, {name: "Carl", ocupation:"Geek Ambassador"}, {name: "Blake", ocupation:"Superstar Moderator and JS wikipedia"}, {name: "Jonathan", ocupation:"Superstar Moderator and Browser-Quirks reference"}, {name: "PointC", ocupation:"Superstar Moderator and SVG Mastermind"} ]; When adding this to the virtual DOM you can use the map array helper: render(){ <div className="staff-wrapper"> {els.map((element, index)=>{ return <div className="staff-card" ref={element.name}></div>; });} </div> } Now when it come to select them all, normally we use querySelectorAll or getElementsByClassName. I'm not very familiar with the specs of this methods, but I can assume that they involve some traversing the DOM tree looking for elements that match the argument. In this case we're setting the ref name for every element by hand, so we have full control over that aspect of our code, so we can loop trough our collection again, matching the ref name using a for or forEach loop, or even using the map method to get a new array: // to create a single animation for each element els.forEach((e,i)=>{ TweenLite.to(e, 1, {rotation:360}); }); // to create a stagger animation const targets = els.map((e,i)=>{ this.refs[e.name]; }); TweenMax.staggerTo(targets, 1, {rotation:360}, 0.1); Here are a couple of samples of a marquee I made for a React app using the modifiers plugin, this is just a simple prototype because I'm bound by some silly NDA for the complete code . This is just React and CSS: And this uses PIXI, just an experiment to see if there was a better performance, since the real thing uses images and text: Well, that's about it, hopefully this helps to make things clear about this and other questions regarding React. Last but not least, @Carl, thanks buddy, is always a pleasure to come back home. Things are going pretty well, still not having a lot of free time but hopefully at some point I'll be back full-time. It certainly feels good when I post an answer or a thread and everyone welcomes me, I feel like Norm in Cheers Happy Tweening!!!
  13. TimelineMax/attrPlugin not working with React

    Hi, I was passing by to se the new features in the forums and ran into this post and I thought I'd offer some tips about using GSAP and React. First the following is a big NO-NO: Never use regular selectors while working with React. This because the component could get an update later and re-render. In this case the id(s) could change or even a DOM node with a specific ID could not be render again, then you get the can't tween a null target error. This goes to master Doyle as well, but we'll forgive his sins because He has given us GSAP . To get a specific element just use this.refs, that points to the node being rendered in the DOM. Second, you added almost 300 lines of SVG code on the component's render method, try to avoid this in order to keep your components small, clean, easy to read/debug/maintain and reusable, which are the cornerstone of component-based development, not only with React, but also with Angular2/4+, Vue, etc. If you can break your svg into smaller component it'll be very easy, remember: "Divide and Conquer" Finally is not necessary to use the bracket notation on JSX. Keep in mind that the component's reference is an object, so you can pass an string to it and React will look for that ref attribute on the code and pass whatever string to the object: render(){ return <div ref="myDiv"></div>; } // Then React does this (this is very simplified of course component.refs["myDiv"] = nodeObject; // So you can access your node this.refs.myDiv; So a real GSAP code could be like this: componentDidMount(){ const target = this.refs.targetGroup; TweenLite.to(target, 1, {}); } render(){ return( <svg xmlns="http://www.w3.org/2000/svg" id="svg2" version="1.1" viewBox="0 -10 573 367" height="367px" width="573px"> <g ref='targetGroup'> // svg code or component here </g> </svg> ); } As for the attribute plugin part, Jack has that already working so no need to go into that. Happy Tweening!!
  14. Detect reverse start event

    Hi, In the case of TweenMax/TimelineMax instances, yoyo does not acts as reverse(), the yoyo feature basically alters the direction of the repeat feature. From the docs: yoyo : Boolean - If true, every other repeat cycle will run in the opposite direction so that the tween appears to go back and forth (forward then backward). This has no affect on the "reversed" property though. So if repeat is 2 and yoyo isfalse, it will look like: start - 1 - 2 - 3 - 1 - 2 - 3 - 1 - 2 - 3 - end. But if yoyo is true, it will look like: start - 1 - 2 - 3 - 3 - 2 - 1 - 1 - 2 - 3 - end. What I can suggest is to detect the direction of the instance or the progress value inside a function and use that on the onRepeat callback: // at startup the direction of an instance is forward // THIS IS NOT RELATED TO THE REVERSED STATUS var forward = true; function cBack(){ forward = !forward; if( !forward) { // the instance is repeating from the end to the start } else { // the instance is repeating from the start to the end } } TweenMax.to(el, 1, {vars, onRepeat:cBack}); Codepen sample: http://codepen.io/rhernando/pen/WRvVqN?editors=0010 Hopefully this makes things a bit more clear. Happy Tweening!!
  15. Run sequence of animations on keypress

    Hi Nate, The issue here could be resolved using TimelineMax, labels and the tweenTo and tweenFromTo methods. http://greensock.com/docs/#/HTML5/Sequencing/TimelineMax/tweenTo/ http://greensock.com/docs/#/HTML5/Sequencing/TimelineMax/tweenFromTo/ Also it could be solved using just labels and the play and reverse methods using the labels as starting points: var tl = new TimelineLite({paused:true}); tl .to(element, 1, {vars}, "label_1") .to(element, 1, {vars}, "label_2") .to(element, 1, {vars}, "label_3") .to(element, 1, {vars}, "label_4"); // then on the click/key events function eventHandler(label, direction){ switch (direction) { case "forward": tl.play(label); // plays the timeline from the specific label break; case "back": tl.reverse(label); // reverses the timeline from the specific label } } // then calling the function eventHandler(forward, "label_2");// plays from label_2 Unfortunately I don't have time to create a working sample of this. Hopefully this is enough to get you started.