Jump to content

Carl last won the day on April 8

Carl had the most liked content!


  • Posts

  • Joined

  • Last visited

  • Days Won


Posts posted by Carl

  1. First, most of the time if you want different animations for different screen sizes I would strongly suggest using scrollTrigger.matchMedia() as it allows you to create drastically different animations and layouts.


    In this case it seems you just need a bit of responsive flexibility.


    Again, function-based values and invalidating tweens on refresh can help greatly.


    here is a great explanation of function-based values in tweens: 



    the demo below will the animation will reset itself when you resize so that the red boxes will all be pinned and moved across the screen as you scrub until the blue box comes into view. open in a new window and resize.


    See the Pen OJaLwgz?editors=0010 by snorkltv (@snorkltv) on CodePen


    ScrollTrigger does a lot of highly optimized, amazing work under the hood so that things like this are seamless and painless.


    Hope this helps.




    ps. If you really want to get into the finer points of GSAP and ScrollTrigger you may want to consider my GSAP Course Bundle.



    Also, if you do need tweens to be constantly changing their target value you may find the ModifiersPlugin of interest too



  2. Hello and welcome to the GreenSock forums.


    Thanks for the demo.


    For a single tween you can just use repeatRefresh on that tween.


    from the docs:

    Setting repeatRefresh: true causes a repeating tween to invalidate() and re-record its starting/ending values internally on each full iteration (not including yoyo's). This is useful when you use dynamic values (relative, random, or function-based). For example, x: "random(-100, 100)" would get a new random x value on each repeat. duration, delay, and stagger do NOT refresh.



    See the Pen BaGBYoo?editors=1111 by snorkltv (@snorkltv) on CodePen


    you will note that the x value is function-based. on each repeat that getX function will run and return the most recent value of x.

    The tween will always repeat from 0 to the latest x value


    You can also set repeatRefresh:true on a timeline and all tweens will be refreshed when the timeline repeats.



    • Like 3
  3. Thank you for the demo.

    I removed the drawSVG code and just added a little code to color each of the 5 paths a unique color

    See the Pen ExdBrYO by snorkltv (@snorkltv) on CodePen


    It appears the paths have some odd gaps in them. The green path is part of the ear on the boy and then it's also most of the girl but her arm has multiple paths (blue and yellow).


    I'm not sure if this makes it somehow impossible for drawSVG to calculate stroke lengths and such, but my general advice is to start with much simpler paths. Draw them one at a time and test with DrawSVG often.


    DrawSVG handles multiple, continuous paths just fine.

    I don't think there was any problem with your actual code.



    • Like 3
  4. Hi @iDVB


    I don't have the time to try to figure it out, but I think it would be worth looking at the Inertia Plugin 


    Investigate both demos with snapping enabled (not live snap)


    You'll see the elements you throw or flick will very naturally end at the proper snap location.


    A core feature of the Inertia plugin is to apply a velocity to something and over time it will naturally slow down.


    Inertia Plugin has features to track the currently velocity of things and allow you to create a new tween with that velocity passed in as the starting velocity. Also, if you fail to throw something hard enough it will naturally glide back to it's starting state.


    I think the key to what you want to do is to track the velocity of your scrolling and apply that to the progress() of an animation.

    The Observer plugin has functionality to track wheelspeed velocity. I'm guessing you could use that in conjunction with the Inertia Plugin





    I think the tools are available here to accomplish your goals, but it will take some tinkering and perhaps a very different approach.






    • Like 2
  5. Hi


    in the future it would really help if you could provide a minimal demo.


    #1) I am trying to get the height of the sections since the height varies. This is for the 'end' parameter in the ScrollTrigger.


    ScrollTrigger automatically measures the trigger and you have access to its "bottom" so you can just test when the bottom reaches a certain point. For instance if you want a section to end when its bottom reaches the top of the viewport you would just use 

    end:"bottom top" (which is the default). If you want the measurement perhaps you just need element.offsetHeight. I log this out in the demo.


    #2 add and remove class names

    you can use classList.add() and classList.remove()

    you'll see in my demo I store a reference to className, previousClassName, and nextClassName so that each scrolltrigger can do stuff regarding the next and previous sections class names.


    Since you have sections with different heights it may be possible that multiple sections are visible fully at the same time. the way the demo is currently set up each section will set its className to the body when it enters the viewport in both directions. when it leaves the viewport in both directions it will remove its class as well


    See the Pen NWOBJde?editors=0011 by snorkltv (@snorkltv) on CodePen


    notice when you got to the bottom of the page the body will be purple and just a little bit of the bottom of the pink section will be visible up top.


    if you scroll back up pink will come into view but the  background won't become pink because the bottom of the pink section never crosses the top of the viewport. bottom of blue will come into view but since purple may still be a bit visible you won't see the background turn to blue until the purple class is removed (when purple top passes bottom of viewport).


    This may seem awkward but it's behaving as it is told and things like this only come up if you have many short sections.

    Hopefully this demo shows enough for you to tweak it to your needs. 



    • Like 3
  6. cool animation. I don't understand everything about the code, the problem, or the exact solution you need. 


    But assuming the end goal is a seamless loop try updating your loop timeline like so


    const TRAIL_LOOP = gsap.fromTo(
      { time: 1.84 },
        time : 3.69,
        repeat: -1,
        ease: 'none',
        duration: 3,


    When it it first loads it will start somewhere around halfway through and then play through to a similar looking part of the loop.


    I got those mystery numbers by playing around with GSDevTools a bit on TRAIL.


    Since TRAIL doesn't repeat you can animate the time() instead of totalTime(), but it doesn't really make a difference.

    I got rid of what I thought might be the cause of some of the glitchiness by setting immediateRender:false on the fromTo tween.

    Again, not really sure of the exact particulars. 


    Hopefully this helps somewhat.

    • Like 2
  7. i was playing around with this last night and was kind of embarrassed with what I came up with.



    First, this highlight function adds or removes the active class

    function highlight(card, isActive) {
      if (isActive){

    Then I use this "wall of callbacks" to toggle the active class as the playhead passes through "the active zone".

    rawSequence.fromTo(item, { scale: 0, opacity: 0 }, { scale: 1, opacity: 1, zIndex: 100, duration: 0.5, yoyo: true, repeat: 1, ease: "power1.in", immediateRender: false, id: "currentItem" }, time)
                .fromTo(item, { xPercent: 400 }, { xPercent: -400, duration: 1, ease: "none", immediateRender: false }, time)
          //start wall of callbacks
          .call(highlight, [item, false], time+0.44)
          .call(highlight, [item, true], time+0.45)
          // this is the active zone
          .call(highlight, [item, true], time+0.55)
          .call(highlight, [item, false], time+0.56)


    each card animation is one second long so at exactly a time of 0.5 is when it is full scale and opacity.

    with the approach above I have one second of time from 0.45 to 0.55 where the active class is applied via the highlight callback.

    On either side of that range I have callbacks that remove the active class.


    See the Pen wvYzeYr?editors=0110 by snorkltv (@snorkltv) on CodePen


    I initially tried to just set the active class at 0.5 exactly. It works fine, but with the easing it seems like you're kind of waiting for the animation to finish before it gets set. feel free to activate this chunk in the demo. 


          .call(highlight, [item, false], time+0.49)
          .call(highlight, [item, true], time+0.50)
          .call(highlight, [item, false], time+0.51) 


    again, I'm not super confident this is the most elegant solution but figured it might help you think of ways it could work. 


    I imagine if you knew the direction the animation was being scrubbed you could determine whether or not the the active class should be applied or removed and avoid my brute force wall of callbacks.


    while I'm here I'd like to applaud at @geedix for supplying an answer that certainly works quite well. 

    • Like 5
  8. hmm, I don't think I understand fully because if you "still want to add fade in but without connecting it to scrub" my suggestion would just be to set scrub:false or don't set it at all. 


    However, doing that I think it would kind of odd to have pinning set to true if the animation just runs on it's own. The user would then be scrolling without anything on screen moving or animating in any way.


    I'm a bit lost at what you want but perhaps a happy medium is having each line stagger in each of its words with a slight fade.


    Scroll slowly below:


    See the Pen NWOxYMe?editors=1010 by snorkltv (@snorkltv) on CodePen


    The basic idea is that each line has it's own ScrollTrigger. Perhaps this will help.

  9. Thanks for the demo. If I understand correctly you can use a value very very close to 0 for the duration like


    duration: 0.0001


    Your tween is being paused at a time:0 but you also have the first item in the stagger have a duration of 0 with unique start and end states. It's kind of a logical nightmare to handle, and GSAP most often handles it swimmingly. In your case a super low duration gives some amount of time between the start and end and yet will be virtually imperceivable. 


    The solution from @mvaneijgen is very clever and works great too!

    • Like 1
  10. Hi and welcome to the GreenSock forums,


    Thanks for the demo. It looks like you got the animation working nicely.


    Can you please clarify what you mean by "iterate a racetrack"?

    Do you want the animations for each track to play one after the other?

    Do you want multiple arrows on each track?


    Just try to be as descriptive as possible regarding the end result you are looking for. Thanks.

  11. Thanks for the great demo!


    I believe at one point the decision was made that if the playhead was sitting at a time where there was a callback that already fired and playback resumed then the callback wouldn't run again. It's one of those situations where you could argue both behaviors (fire again or don't) but there needed to be a consistent way for it to be handled.


    When the playhead lands on a callback and plays or reverses you can optionally set suppressEvents:false so that callbacks will fire (default is true).

    See the reverse() docs


    Since the playhead is already at the end of the animation in your example suppressEvents doesn't really apply (the playhead isn't landing there).


    The cleanest solution would be to force the playhead to instantly move to the end of the timeline from somewhere else and  reverse with suppressEvents:false like so



        tl.time(0).reverse(tl.duration(), false);


    See the Pen abRdEMK?editors=0011 by snorkltv (@snorkltv) on CodePen


    • Like 4
  12. I happen to have a lesson that uses a similar setup in my GreenSock course bundle. I keep things as minimal as possible with design so that my students can focus on the code and add their own flair.


    The main point of this setup is just to get one thing to expand/open when you click on it and close other open things. Flex-box handles "pushing things around" automatically which is a nice bonus. The code is fairly well commented.


    Perhaps this will help you with some of your project.


    See the Pen YzGpXWO by snorkltv (@snorkltv) on CodePen


    * note: when an item is open you can close it using the "x" button OR you can click on another closed item.


    • Like 2
  13. This is very nice effect. I could see myself using this in a tutorial sometime soon.


    in addition to what @Cassie suggested I would add that it would help to have a better understanding of what you know about GSAP and ScrollTrigger, as it could be a challenge if you are just starting with GSAP. 


    Are you looking for us to give you the full solution or just help you with where you are stuck?


    The animation of the orange line could be done a few ways, perhaps an SVG stroke or a colored div moving inside another element with overflow hidden.


    If you inspect the page your referenced you will see that each of those sections has its own orange line that moves.


    I don't have a ton of time now to build this whole thing but I can give you this starting point:


    See the Pen XWxJqGQ?editors=1010 by snorkltv (@snorkltv) on CodePen


    After you've read the ScrollTrigger Docs (watch the full video)  ScrollTrigger Getting Started in 3 Easy Steps I'd encourage you try to wire the animation I provided to a ScrollTrigger. Fork the demo and post it here if you get stuck. 


    hint: use scrub:true


    the repeat is only on the animation so you can see how it works.




    • Like 3
  14. I'm sorry, what does "something goes wrong" mean?

    Sometimes we aren't seeing the same thing as you or know the expected results. 

    please try to be more descriptive. thanks

  15. That extra space is probably due to the 3000px you have in your end value.


    Questions about this type of layout come up a bit around here.

    I'm in the process of making a lesson.

    The video in this tweet gives some background on the basic setup


    I added a little animation on the right in this updated (yet not finished) demo


    See the Pen MWPgoXV by snorkltv (@snorkltv) on CodePen

    • Like 3
  16. Thanks for looking and for the explanation.

    9 minutes ago, GreenSock said:

    By "weird values", do you mean 1px different?

    yup. the circle is inside the scrollbar element. the scrollbar element is being centered, but I expected that the circle would always have a native / starting y of 0 relative to its position inside its parent. I guess I haven't seen the size of the window impact transforms of child elements like this before. 


  17. Thanks for the demo. I had some similar code laying around that made for an easy upgrade


    See the Pen PodyzXb by snorkltv (@snorkltv) on CodePen


    once you undestand all the draggable values @mvaneijgen referred to you can do quite a bit with them.

    The normalize() utility function makes it easy to get the percent from the minY, maxY, and current y values




    I hit a weird snag with your original demo in that it seems draggable is reporting unexpected minY and maxY values.

    It appears the position and margin css setting you were using were causing them to be set to minY:1 and maxY:251.

    @GreenSock please look


    See the Pen wvEYzgy?editors=0111 by snorkltv (@snorkltv) on CodePen


    EDIT: it seems to get the weird values you have to view the pen in its own larger window. very strange


    EDIT 2: works fine in firefox. issue seen in Chrome and Safari

    • Like 3
  18. On 3/8/2023 at 7:39 AM, mvaneijgen said:

    All his videos are great even if you think you're never going to use it there is a lot of general knowledge to gain from them that you can use in your own projects!


    Hi @mvaneijgen I wish everyone understood the "what and why" of what I do as well as you do! Thx for all the support in sharing my lessons.

    • Like 2
  19. i really can't follow much of the code in your demo (I don't know a lot about pixi and native canvas stuff) and it's been many years since I've touched the old GSAP syntax and bezier plugin.

    However, I was able to find and modify an example from the depths of the archives that might help you a bit conceptually.


    See the Pen mdGMWmB?editors=1111 by snorkltv (@snorkltv) on CodePen


    The basic idea is that you add a bunch of bezier tweens to the same timeline that are offset using the position parameter

    The left and right buttons use tweenTo() to tween the progress of the timeline by small amounts in positive or negative directions.


    For what it's worth, even back then these were fairly advanced concepts so I'm guessing it could be a much to bite off if you are new to the platform. 

    I believe the newer MotionPath plugin would make this quite a bit easier as @mvaneijgen suggested. 

    • Like 4