Jump to content

Tahir Ahmed

  • Posts

  • Joined

  • Last visited

Everything posted by Tahir Ahmed

  1. Great feedback @GreenSock. I think this feedback and this thread may become my favourite one to point to the next time I am having a debate on this topic with anyone; along-with the why-gsap and kilobyte-conundrum links of course. This thread has addressed a number of great points from all of you. Thanks everyone. And massive thanks, again, for this really important tool that you introduced years ago, that you have put so much effort into it over the years and still are continuously doing so. Two thumbs up.
  2. I think you are looking for an overlapping animation if I understand it correctly. I think you can achieve this in a number of ways but here is what I would propose with slight modifications to your animations timing and the properties that are actually animating but most importantly, utilising position parameter and nested timelines: var mainTimeline = new TimelineMax(); $('.animated').each(function(index){ var tl = new TimelineMax(); tl.from($(this).find('.image'), 0.6, { alpha: 0, y: -20, ease: Power2.easeOut }, 0); tl.from($(this).find('.title'), 0.6, { alpha: 0, y: 10, ease: Power2.easeOut }, 0.2); mainTimeline.add(tl, '-=0.6'); }); $("#play").click(function() { mainTimeline.restart(); }); To understand more about this position parameter in the world of GSAP, I strongly recommend you to take a look at this in-depth article explaining all the different ways you can use it: https://greensock.com/position-parameter. Hope this helps.
  3. If I am not wrong, this is possible using _gsTransform object that GSAP adds to any target object. Take a look at this as an example.
  4. I could be wrong but don't you think that your second `[].forEach()` call should have `.js-button` as its target elements rather than the same `.jq-button`? Does that help?
  5. And of course, you can go really crazy with these ideas Here is an update to the same: jsFiddle. P.S. I wouldn't exactly recommend the approach though as these are all `div` elements so your browser won't really appreciate it If you really are interested in these kind-of "particle" effects, I recommend going down the canvas route. Pixi.JS is pretty amazing at that. You can use it with GSAP of course
  6. Here is a demo using the technique @Jack described: jsFiddle.
  7. Understand about the image dimensions. I am curious though if it did improve any rendering for you, i.e. a solution using an overlaying element of top of an image to reveal it by animating `translateY` over anything else, even if you are unable to utilize it. And sure, do share what you have and I can help as much as I can. Re `yPercent`, I recommend reading the blog about the release of 1.13.1 version of GSAP. This feature has been available for a while now.
  8. Don't really notice much difference here on my Macbook but my guess is the browser is having a hard time render a very large image (5615x2907 pixels) or it could be that you are animating `height` that is causing problems. If animating `height` (which, in many cases, could produce janky animations) is the cause, here is a forked version with a few amendments for you to try out. As I said, I didn't notice any difference for me in the first place so I can't really tell if this forked version will do any good, but give it a try and let me know how it goes.
  9. Hi @jesper.landberg, Without a reduced test case, it is difficult, for me at least, to tell you why your animations don't run smoothly on Safari and what can be done to make them better. Could you make a demo for us that runs your animations smoothly on Chrome and Firefox and doesn't run well on Safari? As for the questions, here are the answers, based on the little understanding I have about the system: I think It depends on use-cases. However I find that its best in most cases to let the engine decide for itself hence `auto`. Link. As of 1.15.0, `force3D` is set to `auto` by default. No need to explicitly set it in your tweens. The other two values are `true` and `false` to either force GPU involvement or not. Having said that, there is a way to apply `force3D` globally by doing: `CSSPlugin.defaultForce3D = true; /* 'auto' or false */`. Link. Search for `force3D` in these forums and you should find plenty of posts regarding it. Hope this helps in some way.
  10. I think this is happening because there are a number of differences between the logo animation this website has and the codepen version @ThePixelPixie is having, mainly: The number of `companies` elements in the website is 5 but the codepen version @ThePixelPixie has is 4. The number of `company` elements in each of the `companies` elements in website is 15 but in codepen it is only 2 (and in one case, 3). The code in JS is mainly catering for the numbers of `companies` (and `company` element in each of those `companies`) elements and is tightly bound to that. Just to try it out, make duplicates of `company` element inside `companies` element to have them exactly 15. And also make sure that the number of `companies` elements is exactly 5 by duplicating as well. This should make the code work fine. However, to make it flexible / scalable and adopt to your needs (i.e. 4 `companies` elements and perhaps 2 `company` element in each of those), there is some work that needs to be done in the code. Here is forked version of the pen with these updates. Also, you don't need to include TweenMax via <script> tag if you are already loading it via the Settings of codepen along-side jQuery. Hope this helps in some way.
  11. Now that I think about it, @Jack's solution works the best and this situation was a perfect fit for `stagger` methods as he described. I missed that by a mile, how could I do that didn't even cross my mind .
  12. Should be easier to achieve, here is your resulting fiddle. JS: var cloudDrizzle = document.querySelectorAll('#cloudDrizzle2 .climacon_component-stroke_drizzle'); var duration = 1; var firstTimeline = createTimeline(cloudDrizzle[0], duration, 0); var secondTimeline = createTimeline(cloudDrizzle[1], duration, duration * 0.6); var secondTimeline = createTimeline(cloudDrizzle[2], duration, duration * 1.2); function createTimeline(target, duration, delay) { var timeline = new TimelineMax({ repeat: -1, delay: delay }); timeline.fromTo(target, duration, { opacity: 0 }, { bezier: { values: [{ opacity: 1 }, { opacity: 0 }]}, ease: Power1.easeIn }, 0); timeline.to(target, duration, { y: 21, ease: Power1.easeIn }, 0); return timeline; } Hope this helps. Not very sure if I understand your second question i.e. separate functions for `opacity` and `translateY`. Can you elaborate more on that please?
  13. Hi Carl, Thanks a lot for the nice words. I am still learning And thanks a lot for the detailed explanation as well. In fact, I currently use the same technique whenever I have to deal with such situations i.e. create a timeline without delays and another layer of management on top of it all to handle the _pauses_ and yes, usually it means using the `.delayedCall()` method. I can see the reason why this would be just too impractical to bake something like this in the core and thus not worth the effort. Performance (file-size and computations) being the top reason. Far too many scenarios to handle. Consider this chapter closed. For now at least. Thanks a lot again
  14. Hey @OSUBlake, cannot speak for @ald603 but I am, in general, interested in an idea of skipping `delay` and overall gaps put in a timeline using `position` parameter (e.g. intentionally creating gaps using the `+=` operator in `position`) by having some kind of a fast-forward control over a timeline. I am pretty sure it doesn't exist in GSAP system yet but I can see the benefits of having such a feature, this problem here by @ald603 is a prime example of such a use-case.
  15. I could be wrong but I think you don't need the parts with this `clicked` variable. Not entirely sure why you have them there in the first place but these are the parts enforcing you to click twice in order run the animation so I think the final code should look like: var buttonOne = $('#one'); buttonOne.click(function() { tl1.tweenTo('first', { onComplete: function() { this.timeScale(1); } }).timeScale('7'); }); Hope this helps. P.S. I am also curious in knowing the answer to the 2nd question you posted above i.e. a way to skip pauses defined in a timeline. There are a number of situations where I could see this being useful, your situation is a prime example of it. Perhaps someone here can answer this, I would like to know as well.
  16. While @PointC's solution is spot on, clean and does the job well, I however, out of curiosity, looked up the documentation and found out that there could be another way of going about it, which is the by the use of `.invalidate()` method. (This is one of the things I like the most about this suite of tools that there are multiple ways to solve any given problem). As the documentation itself aptly puts: So, as an alternate approach, take a look at this simple jsFiddle, JavaScipt of which is as belows: var myDIV = document.querySelector('div'); var width = 100; var tween = TweenMax.fromTo(myDIV, 0.8, { position: 'absolute', top: '50%', left: 0, yPercent: -width * 0.5, xPercent: -width, width: width, height: width, backgroundColor: '#cc0' }, { x: '+=150', onUpdate: onTweenUpdate, onComplete: onTweenComplete, callbackScope: this, ease: Power0.easeNone }); function onTweenUpdate() { var currentX = myDIV._gsTransform.x; if (currentX >= window.innerWidth + width) { TweenMax.set(myDIV, { x: 0 }); tween.invalidate().restart(); } } function onTweenComplete() { var currentX = myDIV._gsTransform.x; if (currentX >= window.innerWidth + width) { TweenMax.set(myDIV, { x: 0 }); } tween.invalidate().restart(); } I am happy to have learned something new myself thanks to the problem you presented Happy Tweening!
  17. Hi @BlackPixel, Welcome to the forums! This is a lot to comprehend, at least for me personally, and I would strongly recommend you to create a demo for us to better understand your problem so that we are able to propose a solution to it. By the sounds of it, the solution could be simple but we need an example to work with. Take a look at this post on how to create a Codepen demo with GSAP loaded in it. You can then include your minimalist code example of what you are trying achieve. Let us know.
  18. Hi @anu, welcome! This should be easy to fix. What you seem to be missing is concatenating the `name` part (which is a constant string) with a value of an iterating variable `k`. You also seem to be missing the `#` part in a CSS selector which lets you select elements by ID. So your `tl.add(...)` lines probably need to look something like this: tl.add(TweenLite.from('#name' + k), /* the rest follows */)); While I am at it, I would also recommend a few things: First off, I would rather suggest you to use `class` instead of `id` in order to do more things to a set of elements instead of targeting one unique element on a per-need basis. Then, I would recommend you to use shortcut methods provided by TimelineMax (and Lite) versions, such as `.from()`, `.fromTo()` and `.to()` instead of using `.add()` (and then passing a `TweenLite.to()` instance to it). These are convenience methods, it just makes the whole thing appear a little more cleaner in my humble opinion. Both options are valid. Then, I would ask to you to try and avoid animating `left` attribute of any element and instead would recommend you to always look for ways to animate `translateX` (which in GSAP world is referred to simply as `x`) property of any object. Have a read of this article which aptly explains the benefits of animating `translateX` over `left`. Lastly, I would rather ask you to look into `.staggerFrom()` method (and its siblings `.staggerFromTo()` and `.staggerTo()` methods) to avoid the loop entirely and to probably add a nice staggering effect to your transitions. Take a look at this fiddle as an example with all the recommendations, stated above, implemented. JavaScript of which looks like below: var someDiv = document.querySelector('.someDiv'); var array = ['content1', 'content2', 'content3']; var length = array.length; var myVar = ''; var elements = null; var tl = new TimelineMax({ paused: true }); for (var i = 0 ; i < length; i += 1) { myVar += '<div class="name">' + array[i] + '</div>'; } someDiv.innerHTML = myVar; elements = document.querySelectorAll('.name'); tl.staggerFrom(elements, 1, { x: 40, opacity: 0, ease: Back.easeOut.config(2) }, 0.2); tl.play(); Hope this helps.
  19. `Power0`, `Power1`, `Power2`, `Power3` and `Power4` are just more intuitive names for `Linear`, `Quad`, `Cubic`, `Quart` and `Quint` respectively. Read more about them here. You can use either.
  20. Hi @friendlygiraffe, If I am not wrong, there is no `.EaseNone` (i.e. UpperCase) but it is supposed to be `.easeNone`. So your ease value should look like: `ease: Linear.easeNone` (i.e. camelCase).
  21. Hi @venn, I think you can use `repeat: 1` along with `yoyo: true` in order to make them return to their original positions. Take a look at this simple fiddle for example. The takeaway is: timeline.to(top, animDuration, { y: 0, repeat: 1, yoyo: true, ease: animEase }); timeline.to(right, animDuration, { x: 0, repeat: 1, yoyo: true, ease: animEase }); timeline.to(bottom, animDuration, { y: 0, repeat: 1, yoyo: true, ease: animEase }); timeline.to(left, animDuration, { x: 0, repeat: 1, yoyo: true, ease: animEase }); Hope this helps.
  22. Hi @PeTaWeb, TimelineMax's `.from()` & `.to()` methods have fourth, `.fromTo()`, `.staggerFrom()` & `.staggerTo()` methods have fifth and `.staggerFromTo()` method has sixth (and other methods have), parameter which takes care of `position` of your tween. Please take a look at this tutorial on understanding this position parameter and how you can use it: Timeline Tip: Understanding the Position Parameter. Also look into the documentation of each of those methods linked above.
  23. It would. If I understand it correctly, the change will be represented across. Both are referencing the same `tl` instance. Take a look at this for a demo and observe the log messages in your browser's console window.
  24. Yeah. Setting individual classes to elements is a bit redundant in this case. Even if you continue to use your approach, i.e. looping, you still shouldn't really need to give them unique class names. The duplication should carry over the default `cloud` class name that you gave to your original element. And then, you can use that to `querySelectorAll` to return you the array of items containing `cloud` as their class names. But yeah, `stagger` methods are pretty darn cool. And with the recent update of being able to `cycle` through the items, took it to another level entirely. Glad I could help.
  25. Hi @spacewindow, First off, `.stagger...()` methods, if I understand them correctly, are convenient methods. You can totally do without them. I am not sure if they add any performance value, I guess this is something @GreenSock can comment on. Having said that though, I would definitely recommend looking into `.stagger...()` methods as they don't only abstract the loops away (hence less code to write) but it also comes equipped with a few more convenient tricks. For example, consider my pen again, and assume that you wanted to generate 10 clouds in total. Now imagine if you wanted to place each of the `cloud` duplicate that gets created in 3 absolute positions (e.g. `x` to be placed on 100, 150 and 200 pixels but alternating between them in a way that the first `cloud` instance gets to be placed at 100, 2nd on 150, 3rd on 200, 4th on 100 again and so on ...). Now of course this can be written purely in vanilla JS but `.stagger...()` syntax of the same would look like: TweenMax.staggerTo(clouds, 0, { cycle: {x: [100, 150, 200]} }); Easy-peasy? All I can say is that I am a big fan of stagger methods And yes, originally, you were re-populating the same timeline over and over again which is what was the main reason of the weird end-results you were getting.