Jump to content

Rodrigo last won the day on March 17 2019

Rodrigo had the most liked content!


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by Rodrigo

  1. 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!!
  2. 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!!
  3. 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!!!
  4. 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!!
  5. 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!!
  6. 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.
  7. Hi, Since getChildren() returns an array you can do a simple indexOf() in order to check if the instance is in the parent timeline already: var master = new TimelineMax({paused:true}), child1 = new TimelineMax({paused:true}), child2 = new TimelineMax({paused:true}), child3 = new TimelineMax({paused:true}), children; master .add(child1, 1) .add(child2, 2); // get childs children = master.getChildren(); console.log( children.indexOf(child1) );// return 0 console.log( children.indexOf(child2) );// return 1 console.log( children.indexOf(child3) );// return -1 doesn't exists in the array https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
  8. Hi Kevin, This is not a GSAP issue, but an HTML thing. Looking in google I found these stack overflow posts: http://stackoverflow.com/questions/9620122/stop-html-text-being-highlighted http://stackoverflow.com/questions/3779534/how-do-i-disable-text-selection-with-css-or-javascript The second one should work with the onDragStart method, you could attach the event handler and then remove it if you want, otherwise you can run a loop through all the elements you don't want highlighted and leave it like this. Although the first option would be the one of my choice, using a IE9 and older conditional to use the JS code: http://caniuse.com/#feat=user-select-none Please let us know how it goes, this will be helpful for other users. Happy Tweening!!
  9. Hi, Nice sample, works really well. Glad that you were able to figure it out. By now you're getting into the GSAP way (since today there's a way for absolutely everything, why not GSAP, right? ) and how things work under the hood. From now on, things will get simpler and easier for you, trust me. Great job and happy tweening!!
  10. No problemo. Again, sorry it took us this long to answer. Happy Tweening!!
  11. Hi, It's working for me when I declare the GSAP instance before the wheelnav. Keep in mind that JS reads the entire code before it's executed, saving variables into memory to access them later. Perhaps the issue comes when clicking on the text element of the pie-nav?. I see that it has no effect whatsoever, perhaps the developers didn't consider event handlers in the text or tspan tags. But clicking on the green part (the path tag) always triggers the function regardless of where you declare the GSAP instances. If you remove the text you'll see that it works: <div id='piemenu' data-wheelnav data-wheelnav-slicepath='DonutSlice' data-wheelnav-marker data-wheelnav-markerpath='PieLineMarker' data-wheelnav-rotateoff data-wheelnav-navangle='270' data-wheelnav-cssmode data-wheelnav-init> <div data-wheelnav-navitemtext=' '></div> <div data-wheelnav-navitemtext=' '></div> <div data-wheelnav-navitemtext=' '></div> </div> Also a good way to avoid such issues is to use an immediately invoked function expression (IIFE), like that you can be completely sure that everything will be read before being executed and avoid any possible conflicts. When working with jQuery I use the following: (function($){$(function(){ var animlogo = $("#animlogo"), tween = TweenLite.to(animlogo, 6, {left:"90%", ease:Linear.easeNone}); // declare wheelnav var piemenu = new wheelnav('piemenu'); piemenu.clockwise = false; piemenu.wheelRadius = piemenu.wheelRadius * 0.83; piemenu.createWheel(); piemenu.navItems[0].navSlice.mouseup(function () { //alert('PLAY'); tween.play(); }); piemenu.navItems[1].navSlice.mouseup(function () { //alert('PAUSE'); tween.pause(); }); piemenu.navItems[2].navSlice.mouseup(function () { //('RESET'); tween.restart(); }); });}(jQuery)); That basically covers everything, avoids conflicts and has the document.ready as well. Give that a try and let us know.
  12. Hi and sorry for the late response There are a few things throwing errors in your codepen sample. First you didn't include the GSAP files and also is this code right here: // navigation UI var piemenu = new wheelnav('piemenu'); piemenu.clockwise = false; piemenu.wheelRadius = piemenu.wheelRadius * 0.83; piemenu.createWheel(); The class wheelnav is not defined or included anywhere, so it throws an error. Also the target id does exists but there's no style definition for it so is basically a div with 0px of width and height, and doesn't have a background color neither. Use this css on the codepen and you should see it: #animlogo { width: 50px; height: 50px; background: blue; position:relative; } Finally comment out or remove the wheelnav code and the codepen should work. Then you can add the controller code from the GreenSock collection's codepen. Let us know if you have more questions. Happy Tweening!!
  13. Well if you want to delay the start of the entire timeline and not just a few tweens in it, you could use shiftChildren(), although after you used it you'll have to remove that time if te user clicks on the button to play it immediately. Another option is to create a function and pass a time parameter and use a delayed call to start the timeline: var tl = new TimelineLite(); function startTl(delay){ TweenLite.delayedCall(delay, function(){tl.play();}); } And with the other button just use tl.play()
  14. Hi, Without seeing a live sample I would go with shiftChildren(). All you need to know is where the first instance you want to change sits on the timeline, in order to affect the start time of all the instances from that point until the end of the timeline. http://greensock.com/docs/#/HTML5/GSAP/TimelineLite/shiftChildren/ There could be some other ways to do this, such as using a function to create and populate the timeline and passing a value to change the delay of the specific instances. Also is important to know if all your tweens are in straight sequence or if there's some overlaping or staggering between them. As you can see we could keep discussing about different ways to do this, so if you could provide a reduce live sample that is as closest as possible to your real app, it would be great.
  15. Mhh... my first try would be to do it in the link function of the directive. But I've never done something like this, mostly simple enter, leave and view stuff. Perhaps this article could help you: http://onehungrymind.com/build-super-smooth-rollover-angularjs-greensock-timelinelite/ I'm sure Blake will come with the right answer for this.
  16. Hi, I looked at your sample (thanks for providing a reduce case of the issue) and I'm a bit lost about it. So I'm getting in touch with the Animation Elder's Council seeking their wise advice in this matter . An official answer is coming, please stand by.
  17. Hi, Mainly the issue has to do with the values applied to the letters. When you make the first animation, the letters go from 100 to 0, so far so good. Then on the wavy animation you animate the letters from -5 to 5. So basically when the first animation ends, the letters value of Y is 0 and when the second animation starts, the value of Y is -5 and that change happens immediately, so that's the jump you're seeing. What you could do is create a tween that moves the letters from 0 to 5 and then the endless loop that goes from 5 to -5, in order to avoid the jump.
  18. Hi Oliver, I see two alternatives. One is to create the timelines using the loop and adding a delay on the first instance of each timeline to create the stagger effect: var els = $(".element"), stagTime = 0.5; els.each(function(i,e){ var tl = new TimelineLite(); tl.to({}, (stagTime*i), {}) // then the animation }); The other option is to create the timelines and push them to an array. Then add them to a master timeline using the add method with the stagger parameter: var els = $(".element"), master = new TimelineLite(); stagTime = 0.5, tlArray = []; els.each(function(i,e){ var tl = new TimelineLite(); // animation code here // finally to the array tlArray.push(tl); }); master.add(tlArray, 0, "normal", stagTime); http://greensock.com/docs/#/HTML5/GSAP/Core/SimpleTimeline/add/
  19. You're right is a semicolon. In javascript a semicolon indicates the end of a specific line of code, so when you write this: tl.to('#dot_1, 20', {strokeDashoffset: 0, ease:Linear.easeNone}) .to('#bullet_1', 2, {delay: 3, autoAlpha: 0, transform: 'translateY(40px)'},0);// this semicolon ends the line .to('#dot_2', 20, {strokeDashoffset: 0,ease:Linear.easeNone}) .to('#bullet_2', 2, {delay: 3, autoAlpha: 0, transform: 'translateY(40px)'}0); The first semicolon ends the code line. A little background. In JS libraries such as jQuery, GSAP and many others offer the user the possibility to concatenate methods, by returning the instance after that method. In your code the dot_1 instance is added, then there's another to() instance for bullet_1. The first instance returns the timeline (tl) so basically you can attach another GSAP valid method for a timeline(look in the docs). But when you put a semicolon at the end of the to() instance, or any other GSAP instance, in JS it means that the particular line of code that started with the first tl.to() is now completed. So when you add a new .to() instance after the semicolon, the browser won't know what you're referring to, because you're saying "I want to execute the to() method" and the browser says:"ok, but a method of what object, you're not giving me an object here!!", and an error shows in the console. Just add a semicolon after you inserted all the instances in your timeline: tl.to('#dot_1, 20', {strokeDashoffset: 0, ease:Linear.easeNone}) .to('#bullet_1', 2, {delay: 3, autoAlpha: 0, transform: 'translateY(40px)'},0) //zero tells GSAP to place it at the beginning of the timeline .to('#dot_2', 20, {strokeDashoffset: 0,ease:Linear.easeNone}) .to('#bullet_2', 2, {delay: 3, autoAlpha: 0, transform: 'translateY(40px)'}0) .to('#dot_3', 20, {strokeDashoffset: 0,ease:Linear.easeNone}) .to('#bullet_3', 2, {delay: 3, autoAlpha: 0, transform: 'translateY(40px)'}0) .to('#circle_1', 20, {strokeDashoffset: 0, ease:Linear.easeNone}) .to('#circle_2', 20, {strokeDashoffset: 0, ease:Linear.easeNone}) .to('#circle_3', 20, {strokeDashoffset: 0, ease:Linear.easeNone}); Also the codepen is the same link as before and you keep getting the error and there's a big time gap between circle animations, but they're all happening. Perhaps you should refactor your code and make it as simple as possible.
  20. Yep, as you mention, in that case is better to do that. Normally I don't mix GSAP with state properties, but if there's no other option, as it is your case, that's the better option. You're right the file is quite small actually: https://github.com/hzdg/gsap-react-plugin/blob/master/gsap-react-plugin.js I'll play with it and see what happens behind the scenes, mostly I'm interested in how React is working and if a new GSAP instance is being created on every render or not. But since you mention that there are no performance issues it doesn't seem to be a problem.
  21. Hi, The Lite and Max versions differ basically in the available methods each one has to offer. Using the Max classes is useful when you need to perform more complex operations and you need more functionality such as repeat, yoyo, stagger and some other methods. In the case of timelines is pretty much the same, there are some specific methods in the Max class that the Lite class doesn't have. You need to evaluate that in every project, see what you need and then determinate what class to work with. The great thing about GSAP is that you can start with a TimelineLite and then if you need a Max specific method, you can switch to it with no problem, everything will keep working. Take a good look at the docs: http://greensock.com/docs/#/HTML5/Animation/ The add() method allows you to include anything you want in a timeline at that specific point, you can include a function, an array of GSAP instances, a single GSAP instance, a label, etc. http://greensock.com/docs/#/HTML5/Animation/TimelineLite/add/ The shorthand methods include a TweenLite instance in the timeline with less code and using the familiar constructor syntax: http://greensock.com/docs/#/HTML5/Animation/TimelineLite/to/ Again, this depends on your needs, you need to decide what to include based on your particular project. That depends, you already have your elements stored in variables as jQuery objects, just pass the name of the variable. You can also use the GSAP selector feature to get the DOM element: tl.to("#circle_1", 1, {vars}); Normally when I use {vars} I mean the typical constructor object we all use in GSAP, so yes you need to include the properties you're tweening and the easing functions as well, otherwise if you pass {vars}, you'll get an error. Keep checking the videos, docs and other resources (such as the getting started samples) in order to get a better grasp of GSAP. Happy Tweening!!
  22. Hi and welcome to the GreenSock forums. Thanks for your input in this matter. All opinions are welcome. As you mention react has come to solve a specific issue or fill a gap. Right now is a fast and simple way to create apps in a modular fashion, it's less complex than Angular (the most popular choice now a days) but this improvement comes with a price, as this and other React related topics in this forum can prove. Also is worth noticing that, as BowserKingKoopa and other users have mention, nothing has been broken and/or working in a strange fashion mixing GSAP and React. I've played with some simple examples of React and GSAP using GSAP to work with the DOM nodes as refs and not piping anything GSAP related through the state to avoid rendering the React component on every GSAP tick (every 16ms approximately) because I don't see how that's necessary. And also while animating a DOM element I've changed the value of a state property (which triggers a re-render of the component) and the GSAP instance animating the DOM element also resides in the component's state. My idea is to complete that sample with some nested components and more animations in order to publish it on GitHub and continue the discussion in these topics that have been created. Also I'd like to get some contributions from other users with some live samples of GSAP and React in order to create a collection. Finally BowserKingKoopa I have one question regarding the plugin you linked. It hasn't been updated in two years and originally it's using a very old version of GSAP (1.12.1). Have you tried with a newest version of GSAP?, is there any interest by the creator or other user to update this to a newer version of GSAP? Happy Tweening!!
  23. Hi and welcome to the GreenSock forums. Thanks for purchasing the club membership and glad to hear that you're enjoying the GSAP. Unfortunately, this is the way things go with JS. Since it has to be read by the client there's no other way to go. One alternative is to join every file together, including your particular code and put all the comments at the top, like that if anyone tries to use that, they won't know precisely where to look for in order to isolate the specific plugin. Other than that there's not much that can be done in order to secure the files. Carl and Jack are strong believers of the honor system, respect and appreciation from the developers community (guys like you for example), that value the great job they do and buy the club membership in order to gain access to the premium tools. Happy Tweening!!
  24. Hi, Instead of animating the rotation of the element, perhaps you could try with a starting animation and then change the transform origin property in a circular pattern. The transform origin works on a 2D space, so my idea is to move that point following a circular path. This can be done with a simple circle equation to set the transform orign: https://www.mathsisfun.com/algebra/circle-equations.html The point is that transform origin can not be animated, so you have to create a dummy object and apply the transform using an onUpdate callback: http://codepen.io/rhernando/pen/vItdh Unfortunately I don't have time to create a live sample, but hopefully this is enough to get you started. Happy Tweening!!
  25. In that case use a clearProps in a set() instance, that should solve it. You can use it with specific properties or with all the inline styles applied by GSAP. Please let us know how it goes.