Jump to content


  • Posts

  • Joined

  • Last visited

Posts posted by sashaikevich

  1. Let me begin by saying that this community is fantastic! Over the last few years I picked up a wealth of knowledge, and feel comfortable recreating most animations individually. 

    What I feel I need now, is a deeper understanding of the more advanced stuff. Topics like:
    -  How to monitor if the element is on screen and/or best practices for handling the listeners to minimise resource load (by throttling, by destroying listeners, etc)

    - Scroll smoothing approaches (via a library like locomotive or using gsap's scrub)


    Basically I want to take a deep dive into how sites likes these are made: https://ferrumpipe.com, https://revistaelduende.com

    Have you any forum posts or external resources / tutorials (free or paid) that you can point me to?

    Thank you!


  2. Thanks for the quick reply and the ideas.


    The will-change didn't help. Nor did force3d

    Oddly adding a width did, which is what I might have had when you loaded the animation. 


    This simple line fixed it in my demo

    .tidy-team-layered-wrapper {
      width: 70vmin;

    But in my project the flickering remained, so width is not enough. Though why that of all things fixed the flicker I do not know. Gha!

    (I removed it from the demo, so the issue should be visible again)


  3. As my animation runs, and the layers transition through their x, y, z rotations and font size (which does something fun with the perspective) I"m getting this weird flicker in Chrome that I've noticed in the last 24 hours. 

    I've learned here, that flickering might be a chrome bug, but the "will-change" fix didn't do it for me there. Is there anything else you guys can think of for me to try?


    I set up a demo of just the problematic component, but the flickering isn't there 100% of the time: 

    See the Pen poymMvK?editors=0010 by sashaikevich (@sashaikevich) on CodePen



    See the Pen poymMvK by sashaikevich (@sashaikevich) on CodePen

  4. I recall seeing a nice marquee example, but I can't track it down. Undoubtedly this is a common use-case for a horizontal marquee / scroller (logos, testimonials, etc.). 


    I'd like the beginning of the next animation to trail the end of the one that's about to end. As it is, I have a space between the two.


    Please point me to the example, or check out my code and codepen below:


        repeat: -1,
        defaults: {
          ease: "none",
          x: (i, el) => innerWidth * i
          x: (i, el, t) => -innerWidth * (t.length - i ),
          duration: d,


    See the Pen abNMQyg?editors=1010 by sashaikevich (@sashaikevich) on CodePen

  5. @ZachSaucier, thank you very much for all your help, every time I get something working I get so excited (and come up with 10 more animation ideas)! I have just a small thing left (hopefully), and this page that's been 1 year in the making will be perfect!

    I still cannot get the elements to recalculate their animations in relation to the new innerWidth/Height after a window resize. 


    When I added invalidateOnRefresh: true property to all my ST objects that seemed to do the trick, BUT as a side effect many of my elements lost their correct positions.


    I did a quick check, and I think its everything with the .from() method that's been affected, because my few remaining fromTo animations are still correct (but it might be others as well (.to() maybe, or .set()?).


    If I understood your animation guide correctly, the fewer .fromTo() methods - the better, but is that still the case here?


    Should I go back to using .fromTo() animations and add invalidateOnRefresh OR, should I keep my .from() and my .to() animations and do something else instead of invalidateOnRefresh? 


    I've included a simplified version of my code below if it helps. (Maybe it's some other rookie mistake that's interfering)


    function customCode() {
        // all 
        "all": function () {
        // desktop
        "(min-width: 1024px)": function () {
          let instWrapperHeight = Math.floor(document.querySelector(".instructions-items-wrapper").getBoundingClientRect().height);
          function distFromBottom(el) {
            return instWrapperHeight - (Math.floor(el.offsetTop)) + el.offsetHeight * 1.5;
              scrollTrigger: {
                end: () => innerHeight * 4,
            .to(".welcome-splash", {
              y: () => -innerHeight * 0.5,
            .fromTo(".text-bold", {
              y: (i, el) => distFromBottom(el),
            }, {
              y: 0,
          // SCENE show options
              scrollTrigger: {
                end: () => "+=" + innerHeight * 6,
            .fromTo(".option-3", {
              x: () => innerWidth * .1,
              y: "-100%",
            }, {
              y: () => innerHeight
      let allST = ScrollTrigger.getAll();
      let allSTProgress;
      ScrollTrigger.addEventListener("refreshInit", function () {
        allSTProgress = allST.map((st) => st.progress)
      ScrollTrigger.addEventListener("refresh", function () {
        allST.forEach((st, i) => st.progress = allSTProgress[i])
    window.addEventListener("load", (e) => customCode());


    What do you recommend I do? 

  6. Thanks GS team for providing the Keeping ScrollTrigger same progress on resize codepen.

    How can I adapt this part of the code for multiple ScrollTriggers?

    ScrollTrigger.addEventListener("refreshInit", () => progress = ST.progress);
    ScrollTrigger.addEventListener("refresh", () => ST.scroll(progress * ScrollTrigger.maxScroll(window)));

    I have 12 ScrollTriggers set up, and they are all set up anonymously, like this:

              scrollTrigger: {...

    How can I reference and update the progress for each one?


    I'm hesitant to rewrite them with separate, named timelines, because I noticed that when I crated the scrollTrigger separately for one of my animations using the create method:


    ...and passed in my timeline, the start/end triggers were in the wrong spot. (Even though it was written in DOM order, and ST.sort() was applied, the triggers were still appearing far too early). 



    I'll also be using matchMedia.


    And, is there any advantage to using a function like:

    end: () => innerHeight * 4,

    instead of:

    end: innerHeight * 4,

    Many thanks!

    See the Pen xxVWJGe?editors=1010 by GreenSock (@GreenSock) on CodePen

  7. I'm not 100% sure, but I think there might be a way applying fromTo on the timeScale. I'll have to play around with it some. Thank you very much for your help. And for the animating efficiently writeup. I don't think that's the one I had in mind, but yours might be better! Thanks again!

  8. As an aside, I see you use some clever techniques, like converting the objects to an array and saving them in a variable, instead of doing them on the fly with the built in gsap selector, and setting time to 0.0001 to ensure first frame loads. I recall a post about optimization / best practices on gsap forums or blogs, or somewhere... but I can't find it again. I'd like to refactor my code with best practices once done, rather than have things holding by duct tape. Do you know the page I'm talking about?


  9. I'm happy to use it even without speeding up, that would have been just a cherry on top. 

    The speeding up would happen only on the very first play, so that the site visitor wouldn't be hit with an epilepsy-inducing flashing animation. I wanted the animation to ease into it on first play, and then continue at a constant speed (even after restarting at onEnterBack).

  10. Legend! Thanks!

    Yeah, I'm going to start the play when its scrolled into view, and pause it when its out of view.

    I've ScrollTrigger.create...ed a listener, and am using callbacks with my current method:

    onEnter: cycleRevisions,
    onLeave: pauseRevisions,
    onEnterBack: cycleRevisions,
    onLeaveBack: pauseRevisions,

    With yours, can I just add the animation property and populate it with the timeline variable? (along with the toggleActions)

    animation: revisionTL,
    toggleActions: "play pause resume pause"


  11. I'd like to rewrite my image cycle animation using GSAP's latest code. It's cleaner, plus I want to attach it to the new ScrollTrigger, and fire the animation when it reaches a certain point on screen, and pause when its not in the viewport.


    However, I'm having a difficult time getting it to work. I've found examples using the deprecated cycler, and others using some nifty staggers. I got close with my code, but I just can't get rid of the fade (I'd like the active image to just appear without a transition, and have it stay visible for a fraction of a second).


    Bonus kudos if someone can help the cycle accelerate until a maximum.  @swampthang and @OSUblake both seemed to get this to work by adding a timeScale fromTo tween on the timeline itself 

    See the Pen dpqyzO by swampthang (@swampthang) on CodePen


    See the Pen epLjrG?editors=0010 by osublake (@osublake) on CodePen

    . But, is that possible to do if the animation is going to be triggered by the ScrollTrigger?

    See the Pen eYZLqqX?editors=1111 by sashaikevich (@sashaikevich) on CodePen

  12. On 1/20/2020 at 11:48 PM, ZachSaucier said:

    You should take some time to learn how to use your dev tool's profiler functionality and go through the problematic sections. 

    None of the performance issue has to do with GSAP's functionality. It all seems to be related to the properties that you're animating.

    Thanks again for taking the time. I got to know dev tools a bit over the last 2 days, but the more I look at it, the harder it is to identify the problem areas. I've compared my LP to others in the gsap showcase, and there are a lot of similarities in thread count, js heap sizes, etc.


    So, I did what I could to just optimize it. 

    @OSUblake pointed out that sawtooth is an indication of a memory leaks (

    ). And Jack @GreenSock shared https://css-tricks.com/writing-smarter-animation-code/,  and with the above advice I rewrote the code, getting rid of all my global variables, some fonts, moved my many complex svg out of my document to cut down on nodes, calling them as sprites from a single file instead.


    Now I have 2 optimized versions of my LP:

    https://littleguylogos.com/lp-scroll-opt-1/ which has the above,

    and https://littleguylogos.com/lp-scroll-opt-2/ which is partially complete, whereI use functions to create and add scenes to a master timeline.


    @ZachSaucier can you please have a look , and give me your expert opinion; is there any real benefit to rewriting the entire timeline as I have started to do in opt-2 ? 


  13. 14 minutes ago, ZachSaucier said:

    You should take some time to learn how to use your dev tool's profiler functionality and go through the problematic sections. 

    None of the performance issue has to do with GSAP's functionality. It all seems to be related to the properties that you're animating.

    Side note: the site is over 15mb :( That's a huge website, especially for something without much content. I recommend minimizing that however you can.

    I thought it was a somewhat light page :( 

    All the graphics are svg, and for a graphics rich page, it's only 3.8mb. Why is it 15mb when I do a capture, I don't know...

    It seems to be less choppy when I run it, but I don't know what the problems are that make it choppy for others. 



    Here's a codepen that doesn't work, but has my JS at least. Maybe it's of some help?

    See the Pen qBEQJzJ by sashaikevich (@sashaikevich) on CodePen


  14. Cool. It's here: https://littleguylogos.com/lp-scroll/


    One thing I know I can do, is watch for a screen resize, and recalculate when the height changes (which happens when the tabs and url bars show/hide).

    However, when I kill and rebuild my timelines and scrollmagic scenes on resize, the page position jumps to a completely different section. While that's acceptable on desktop (since it's manually triggered), triggering a resize each time the user changes the scroll direction on mobile (ie an automatic window resize) would make for a frustrating user experience on mobile. 


    And calculating the outer window height in javascript didn't help 😕