Jump to content
Search Community

Carl last won the day on December 24 2023

Carl had the most liked content!

Carl

Moderators
  • Posts

    9,825
  • Joined

  • Last visited

  • Days Won

    546

Community Answers

  1. Carl's post in Last function in timeline is not executed when reversing was marked as the answer   
    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
     
  2. Carl's post in Play and reverse animation by clicking on same element was marked as the answer   
    Hi and welcome to the GreenSock forums. 
     
    immediately after the last tween in your timeline add
     
    tl.reversed(true)
     
    or
     
    tl.reverse()
     
    this way the timeline will be in a reversed state before the first click which means it will play on the first click. 
  3. Carl's post in Two columns animation was marked as the answer   
    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
  4. Carl's post in Random reveal was marked as the answer   
    being that I just did a lesson on cloning groups in my SVG Animation with GreenSock course, I figured I'd take a stab at this.
     
    The top-level approach was:
    take polygons out of pattern in defs wrap them in a group create a loop-inside-a-loop to clone the initial group and place the clones in a grid animate using same technique as above
    See the Pen ZEjNvKw?editors=1010 by snorkltv (@snorkltv) on CodePen
     
    Hope this helps
  5. Carl's post in Step Animation on Bezier Path was marked as the answer   
    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. 
  6. Carl's post in Different animations according to mediaqueries was marked as the answer   
    Hi. It sounds like you are looking for gsap.matchMedia() the docs have an excellent video and a bunch of examples to get you on your way.
  7. Carl's post in Why does transformOrigin not work? was marked as the answer   
    Thanks for the demo. 
    transformOrigin only applies to transforms like x, y, rotation, skew, scale.
     
    width and height are not transforms
     
    for what you want to do I suggest using scaleX.
     
    I wasn't sure where you want the line to start and end, but hopefully this demo points you in the right direction.
    feel free to play with the values.
     

    See the Pen WNKVYGV?editors=1010 by snorkltv (@snorkltv) on CodePen
  8. Carl's post in Gsap.from with scrolltrigger was marked as the answer   
    welcome to the GreenSock forums,
    Thanks for the demo. Unfortunately, the code is a bit much to untangle quickly and I'm not really sure what effect you are going for.
    However, my advice would be to make sure your trigger is not the same thing that you are animating. 
    If you animate the trigger it can mess up all the measurements ScrollTrigger needs to make.
     
    try something like this
     
    <div class="triggerElement"> <div class="targetOfAnimation"></div> </div>  
    If that doesn't help please consider simplifying the demo by removing mapper objects, parsing functions and passing data around through functions like
     
    scrollListner(element, anim1, animateOnce, mirror);  
    I understand it is probably an elegant and effective way for you to code but it causes first-time viewers additional effort to decipher. thanks!
     
     
     
  9. Carl's post in Reverse Timeline onLeaveBack was marked as the answer   
    Hi, 
    i'm not exactly sure what effect you are going for. FWIW it seems a bit disorienting to move something down to a y:200 while scrolling up.
    That aside I would avoid creating 2 timelines initially time that control the same properties of the same thing.
    To avoid conflicts I would suggest creating these animations fresh when you need them inside your callbacks sort of like:
    ScrollTrigger.create({     trigger: ".top-page",     start: "top-=100 top",     end: "top+=200 top",   markers: true,     onEnter: () => {let tl1 = gsap.timeline({})     .fromTo("header",      {         y: 0,         overwrite: 'auto'     },{         duration: 2,         y: 200,         ease: CustomEase.create("custom", "0.5, 0, 0, 1"),         overwrite: 'auto'     })},     onLeaveBack: () => {let tl2 = gsap.timeline({})     .to("header", {         scale: 1.2,         y: 200,     })     .set("header", {y: 200,scale: 1,},"hide")     .to("header", {opacity:1},"start2")     .to(("header"), { y: 0, duration: 1, ease: "power4.out" }, "start2")} }); I would also remove locomotive scroll until you know things are working fine without it.
     
    Hopefully this set up will allow you to remove some of redundancy between the 2 animations like tweening and setting y:200 multiple times.
    If you need more help please try to simplify the animations as much as possible in a fork of the original pen. 
     
     
  10. Carl's post in Issue with GSDevTools was marked as the answer   
    Hi Louis,
    Nice to see you. Greart demo.
    Please try moving the GSDevTools.create() to the very end of your js after the forEach loop.
    It appears to resolve the issue.
     
     
  11. Carl's post in Zooming SVG viewbox was marked as the answer   
    @Rodrigo thanks so much for the kind recommendation regarding my courses.
     
    @NickNo it looks like you have a good understanding of animating the SVG viewBox. Thanks for providing such a nice demo to work with.
     
    I don't have a lot of time to rework this or go over every aspect but hopefully the following will help a bit.
     
    When it comes to interactivity like this it can often become troublesome to manage the states of multiple pre-created tweens especially  since each of your 4 tweens are animating the same thing (viewBox of the svg). 
     
    There are a few variations of how to approach this but the end result should be something that creates the animations that you need when you need them. In your case you should create animations when the user clicks on things. 
     
    Since you provided all of the viewBox settings I went ahead and added them to each group as a data-box attribute
     
    <g id="A" data-box="40 40 400 400">         <circle fill="#FF0096" cx="131" cy="130" r="78"/>         <g>             <path d="M125.3,145.7c-2.3,2.9-7.9,2.9-16.6,0c-1.9-0.9-2.7-2.6-2.6-5.2c1-15.9,7.4-29.7,19.1-41.4c3.3-2.8,7-2.1,10.9,2.3                 c10.6,14.3,15.6,28.1,15.1,41.3c-0.7,4.5-5.9,5.7-15.6,3.8c-2.8-0.7-4.4-4.3-4.7-11c0,0-0.9,0-2.6,0 In the js I create an array of all your groups called btns and loop through it and give each button
    a clicked property of false a click eventListener that checks if the clicked property is false if false then tween to the viewBox to this btns data-box value and set clicked to true if true then tween back to the default viewBox view and set clicked to false const btns = [A, B, C, D] btns.forEach((btn, index) => {   btn.clicked = false;   btn.addEventListener("click", ()=> {     console.log(btn.dataset.box)     if(!btn.clicked){       gsap.to(Wall, {attr:{viewBox:btn.dataset.box}})       btn.clicked = true     } else {       btn.clicked = false       gsap.to(Wall, {attr:{viewBox:"0 0 800 582"}})     }   }) })  
     

    See the Pen WNKvRaj?editors=0010 by snorkltv (@snorkltv) on CodePen
     
     
     
    That gets a bit more complicated as you will have to tie multiple animations together and you have to deal with situations where the user may click fast like: click on A and then B but while A is zooming out they then click on C.
     
  12. Carl's post in Add extra 'padding/time' to end of an animation was marked as the answer   
    to add empty space / time to the end of a timeline you can add a tween on an empty object with the duration of your choosing
    tl.to("#someThing", {x:300, duration:1})    .to({}, {duration:3}) // adds 3 seconds of time at end  
  13. Carl's post in How is the animation performed when the Swiper slider is scrolled? was marked as the answer   
    Thanks for the demo. I don't use React at all so I can't help much with your actual project.
     
    However, I am working on a Swiper lesson for my GreenSock courses so I can share the following as a basic "work in progress" to show how to get the 2 to work together. 
     

    See the Pen XWBNJjK?editors=1010 by snorkltv (@snorkltv) on CodePen
     
    Despite not being able to help you with React I have a few thoughts on what you're doing:
     
    My strong personal opinion is: try to break free of the mindset of "adding css classes to things to trigger animations". Swiper offers events that you can use to trigger your GSAP animations. In my example everything is triggered via the "slideChange".
     
    Next, I'm a bit lost on how you plan to implement scrolling but right now your page doesn't scroll at all. I see what appears to be 3 tweens with ScrollTriggers assigned but I don't understand how the triggers are supposed to enter and leave the viewport to trigger the animations. 
     
    If your carousel is going to be "locked in place" and your page doesn't scroll, I think you could use Observer to help you out. It shouldn't be too hard to wire it up to tell Swiper to go to the next or previous slides.
     
    Hopefully this helps you understand an alternate approach and you can better decide what will work best for your project.
     
  14. Carl's post in Cancel Image Reveal Effect Repeat was marked as the answer   
    thanks for the demo. nice job!
     
    If you want a ScrollTrigger animation to only run once you can set once:true
     

    See the Pen ExpybZV?editors=0010 by snorkltv (@snorkltv) on CodePen
     
    From https://greensock.com/docs/v3/Plugins/ScrollTrigger
     
     
    Boolean - If true, the ScrollTrigger will kill() itself as soon as the end position is reached once. This causes it to stop listening for scroll events and it becomes eligible for garbage collection. This will only call onEnter a maximum of one time as well. It does not kill the associated animation. It's perfect for times when you only want an animation to play once when scrolling forward and never get reset or replayed. It also sets the toggleActions to "play none none none".
  15. Carl's post in Div ease was marked as the answer   
    hmm, I don't what you mean by "it doesn't register the classes".
    As GSAP helper noted it would be a big help if you create a minimal demo. This way we can see the html, css, JavaScript and any errors.
     
    I'm only guessing that maybe you need something like this:

    See the Pen abjbaJd by snorkltv (@snorkltv) on CodePen
     
    The function-based values allow each target to be assigned unique x and y values. You could also write a loop.
     
    If you need more help, please supply a demo.
     
    If you want to get more comfortable with GSAP, you may benefit from my free GreenSock beginner's course. 
  16. Carl's post in Timeline repeat: Play first animation when last animation starts was marked as the answer   
    Hi and welcome to the GreenSock forums,
    Thanks for the clear demo.
    It seems you found an alternate solution but this could work too
     

    See the Pen GRGeJYX?editors=1010 by snorkltv (@snorkltv) on CodePen
     
    This allows the text-1 to fade in from the start.
    Note I set the opacity of all h1 tags to opacity:0 in the css. This removes the flash of un-styled content and makes the looping cleaner as I implemented it using the label. 
     
    You could also approach this using a special stagger technique but I don't want to throw too much at you if you're just starting and you're comfortable with your solution.
  17. Carl's post in Hover runs for all elements was marked as the answer   
    thanks for the simple demo.
    my jQuery is a bit rusty, but I recall that hover would handle 2 functions for mouseenter and mouseleave.
    The biggest issue is that you are creating a new timeline on every hover.
    I don't really know what the end result is but usually it is best to create the timeline once for each element and then control it differently for each mouseevent. 
     
    hopefully the following can get you going in the right direction.
     

    See the Pen VwdQYRb?editors=0110 by snorkltv (@snorkltv) on CodePen
     
    "play none none none" looks like toggle actions for ScrollTrigger and wouldn't apply at all here.
  18. Carl's post in Counter controlled by ScrollTrigger (Uncaught TypeError: func is not a function) was marked as the answer   
    Excellent job as always @mvaneijgen
     
    I just recently learned about toLocaleString()
    const num = 123455.34 console.log(num.toLocaleString()) //output 123,455.34  
    Great for currency too!
     
     
    docs
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString
     

    See the Pen jOKrZJy?editors=0010 by snorkltv (@snorkltv) on CodePen
  19. Carl's post in Changing a tween in a timeline is ignored by the siblings was marked as the answer   
    Thanks for the clear demo. Things are working as designed. Changing the duration of a tween after it is inserted into a timeline does not shift every animation after it. This is done mainly as a performance optimization as it would be quite taxing for every animation to constantly be aware of changes to its duration. 
     
    However, you can use shiftChildren()
    https://greensock.com/docs/v3/GSAP/Timeline/shiftChildren()
     
    demo
     

    See the Pen BaVjjrX?editors=1011 by snorkltv (@snorkltv) on CodePen
     
     
     
     
  20. Carl's post in Noob Question: Affecting Multiple Objects Simultaneously on Single EventListener was marked as the answer   
    that's a pretty cool effect. thanks for the demo.
    Inside the first loop you have access to the index of the text button so you can use that to target its respective digit.
     

    See the Pen MWGVmqq?editors=1010 by snorkltv (@snorkltv) on CodePen
  21. Carl's post in Animate an SVG path around viewbox center not 'self' center was marked as the answer   
    hi Penni,
     
    you can use the svgOrigin

    See the Pen dyeJrVJ by snorkltv (@snorkltv) on CodePen
     
    I don't think your dashed circle is perfectly centered which is why using the center of the svg doesn't look exactly right.
     
     learn more about svgOrigin
     
    or you can modify the transformOrigin so that it lines up with the center of the dashed path kind of like...
     

    See the Pen gOzoEGB?editors=1010 by snorkltv (@snorkltv) on CodePen
  22. Carl's post in Animating each element combined with timeline was marked as the answer   
    thanks for the demo.
     
    Some issues with what you had
    You created 1 timeline outside of the forEach loop. Inside the loop you were creating tweens that had ScrollTrigger options but no animation settings outside the loop you were creating 2 tweens that had nothing to do with what was happening inside the loop. Possibly just some formatting issues crept in over time.
     
    What you want is to create a timeline for each section with it's own ScrollTrigger settings and tweens as shown below
     

    See the Pen ZEoyrXL?editors=0110 by snorkltv (@snorkltv) on CodePen
     
    also your .fade elements all started with an opacity of 1 so animating to 1 wasn't doing anything. I set their opacity:0 in the css.
  23. Carl's post in Tween to Progress instead of Jump was marked as the answer   
    Sorry, without seeing the code that error doesn't give us much to work on.
    There is nothing in the example I provided that requires the use of a plugin.
    My only guess is that whatever you are tweening the progress of isn't an animation with progress() method. 🤷‍♂️
     
    perhaps before the tween that gives the error you can log
    console.log(animation) // does the target of your tween exist? console.log(animation.progress()) // does it have a progress() method //your tween gsap.to(animation, {progress:value});  
    replace "animation" with the name of the tween you are controlling.
     
    you may have to register ScrollTrigger, but I don't think it's related to that error.
    gsap.registerPlugin(ScrollTrigger); 
     
  24. Carl's post in SVG text on a path - stopped working? was marked as the answer   
    thanks for the video. I don't have any windows / android devices.
     
    In the demo below I'm rotating the <text> element. Does that give more consistent results?
     

    See the Pen oNdgJVd by snorkltv (@snorkltv) on CodePen
     
    @GreenSock may be able to shed more light on this, but please understand the company and support staff may be observing holiday hours today
     
     
  25. Carl's post in GSAP target not found was marked as the answer   
    Hi and welcome to the GreenSock forums.
     
    Your gsap code is running BEFORE box is available in the DOM.
    Move your code to the bottom. Usually best right before the closing </body> tag
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.1/gsap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.1/ScrollTrigger.min.js"></script>           <style>         .background{             background: white;             width: 100%;             height: 100vh;         }         .box{             width: 300px;             height: 300px;             background-color: black;         }     </style>     <div class="background">         <div class="box"></div>     </div>  <script>         gsap.to(".box",{             x:500,             duration: 3         })     </script>  
    Check out my free GSAP beginner's course. I think you'll find it helpful
    https://www.creativecodingclub.com/courses/gsap-3-express
     
     
     
×
×
  • Create New...