Leaderboard
Popular Content
Showing content with the highest reputation since 05/10/2023 in all areas
-
Hi @ErwinHeiser welcome to the forum! I wanted to jump on on top of @Carl's feedback with the following pen. DrawSVG can animate strokes, and your current paths don't have strokes only a fill color. As you can see below all your paths have two strokes around the path. If you want to animate something like this you have to redraw them with without a path and only one line with something like the pen or pencil tool from Illustrator, than I think it will look like you want it to. Oh and I also have removed pathLength="1" from the svg, never seen it before and don't know what it is doing and with it looked like it wasn't working. Hoop dat het helpt en veel geluk! https://codepen.io/mvaneijgen/pen/oNarmbv?editors=10105 points
-
Yeah, I'd have to disagree on this. If I add a set tween to the beginning of a timeline I expect the timeline to start at that set state. It's an explicit instruction to immediately set a value. It's not saying 'animate to' Similarly with your demo you've linked above, you've said 'doesn't initially apply' to all the from tweens. But quite the opposite is true, they are all immediately 'applying' by rendering at their end value. Let's break it down a bit - first step, initial positioning ✨ I think potentially the thing that's tripping you up here is referring and thinking of 0 duration tweens as 'animations' The thing is, they aren't animations. Animations imply a duration, in order to animate we have to have some values to animate between and a period of time to 'tween' between those values. What you have here with 0 duration tweens and set 'tweens' are immediate commands. Let's just take a look at the initial positioning. I've added some set tweens, some time stamps so that the starts are staggered and I've got rid of scrollTrigger for now (as that adds some different rendering behaviour which will likely confuse things further) https://codepen.io/GreenSock/pen/MWPxbEa?editors=0010 First thing to know is that all from() tweens render immediately by default. Now, an immediately rendered from tween with a zero-duration will render immediately at the end of the tween, the final state. Because it's a from tween it runs backwards, so you're 'setting' the end value. You'll never see the values in the vars object because those are the initial values. The two tweens and set calls would also render immediately if they weren't on a timeline as they have zero duration. I've added some standalone tweens so you can see this. BUT, because they're on a timeline they're set to immediateRender: false and they're waiting for the playhead to hit them in order to 'set' their position. --- If you bop immediateRender:true on all the tweens (commented out for you in the defaults) you'll see that all the tweens act the same as the from tweens, not waiting for their place on the timeline, just immediately rendering at their end state. Probably worth saying too that 0 duration from tweens are incredibly uncommon and unintuitive. From tweens essentially say 'animate from these values' which is useful. But a zero duration from tween is basically a back to front, upside down set call. 🫠 It's inherently going to ignore everything in the vars object. It makes my head feel funny just trying to read it. So I really don't know why anyone would be using a zero duration from tween in the first place. --- It seems to me that what you're running into and trying to understand is basically immediateRender - So here's some information. it's a little tricky to wrap your head around but it should help things click into place a little. And here's a deeper dive into this behaviour by Jack If that makes sense and we're on the same page I'm happy to elaborate more about the reversing behaviour and how ScrollTriggered timelines differ from normal timeline rendering. ✨ Also, you're not the first to get baffled by this and you won't be the last! ✨ Hope this helps!5 points
-
Sounds like a good use case for clamp() https://codepen.io/PointC/pen/dygQaPj/da853be09052e3296cc321b566e753535 points
-
You're looking for collision detection. There are several threads about the topic around the forum. Here are a few to get you started.5 points
-
Hi, The problem is in the math you're doing for calculating the distance constant. In an ellipse you'll need both the values on the X and Y axis for that, but a triangle circumscribed in a circle it's always an Isosceles triangle, that means both sizes are equal an the angles are 45 degrees: On top of that you are overcomplicating this quite a bit IMHO. This is far simpler, cleaner, seems to work the way you intend and you don't have to worry about the user dragging on the X axis: let radius = gsap.getProperty(table, "r"); const changeCircleSize = Draggable.create(dot, { type: "y", onDragStart: function () { dragCircle[0].disable(); }, onDrag: function () { table.setAttribute("r", Math.abs(radius - this.y)); }, onDragEnd: function () { dragCircle[0].enable(); } }); Here is a fork of your demo: https://codepen.io/GreenSock/pen/poxOpLN Hopefully this helps. Happy Tweening!5 points
-
First off! Hi @livlove welcome to the forum and thanks for being a Club Greensock member 🎉 I'm not completely sure what you're asking. Some times people use two ScrollTriggers one for pinning and one for animating, this is only needed in really specific cases, but can be handy at times. Have you maybe seen the common mistake article about using ScrollTrigger? Mainly the logic issue "Creating to() logic issues". This talks about animating the trigger element, but it also applies animating the pinned element. No I would not think so. Here is a fork of your pen where the pin is on the .animation-wrap instead of the .purple div. I've also removed the fixed from the CSS, because it is better to let ScrollTrigger handle everything. You could also wrap your .purple div in a container and have that as the pinned element, this will fix the logic issues, but will require some extra CSS. Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/mdQyoMV?editors=0010 Did some more digging and maybe changing the fixed to absolute fixes the issue, but I would still not be comfortable animating the element that get's pinned, better is to use separate elements for that to fix potential logic issues https://codepen.io/mvaneijgen/pen/YzRPgvy4 points
-
Hey there @Toliy36, welcome to the GSAP forum. your title pretty much has the answer to your question, as first and foremost you'll need to duplicate your arrow. Place the two arrows so that one of them is visible and one of them is placed "off-canvas", and then tween the visible one out of view, while at the same time tweening the not-visible one into view. This thread here has a couple of approaches / demos you could have a look at. Give it a shot yourself and if you get stuck along the way, please post back with a minimal demo of what you have tried - that makes it a lot easier to help thoroughly. Cheers.4 points
-
Just modify your start/end percentages: https://codepen.io/PointC/pen/qBJzeYJ/892842f1056c3bd18093804305c0d32c Happy tweening.4 points
-
Heya! So smoothOrigin shouldn't be needed in your case at all. Smooth Origin is only for when you're animating between positions that have separate centers of transformation (transform origins) It basically moves the origin point to wherever the transformed element has moved to, so that there aren't jumps. What you've likely got confused about is that the set call is instant, you can't see that transformation happen, so you can't see that the center of origin is different in that set call than in your tween. What's actually happening here is this... You're scaling down the arrow head to the top left corner of it's bounding box, then scaling it up from the bottom left. With smoothOrigin this 'bottom left' position is moved to align with the new position of the arrowhead, so when it scales up, it's in a different place, here's a demo. https://codepen.io/GreenSock/pen/bGmPJoE?editors=0010 This is just an added layer of confusion here because you don't need this behaviour at all, there's no need for you to be animating between different origin points. It sounds like you're just trying to scale the arrow up in the right place right? --- So let's look at transforms. An origin point is basically the center of rotation or transform. Spinning or rotation is easier to visualise, so let's talk about spinning for now. You can think of it like if you were to put a pin in a post it note and spin the paper around, the paper would spin around the place where you've put the pin. The origin. The difference between transformOrigin and SVGOrigin is to do with which bounding box is used for the origin point. You can choose to spin around a point on the element itself, or somewhere on the SVG canvas. Here - You can see one is spinning around it's own top left corner, and the other is spinning around the top left corner of the SVG. you can add overflow visible on the SVG to see, I just kept it hidden for now as it's a little tidier https://codepen.io/GreenSock/pen/YzJoMbK For your example, all you need to do is animate using the correct center or transformation, so something like this? .from(`.ray__arrow--right`, { scale: 0, transformOrigin: 'bottom center', ease: "none" }) @Carl recently did a video on transformOrigin so that might be a good one to check out if you're still a bit baffled! addendum - in terms of SVG vs HTML, the main thing is that HTML dom elements spin around their own center, whereas SVG elements, by default, spin around the top left corner of the SVG canvas. With GSAP the default is the top left corner of the element itself. Hope this helps!4 points
-
I think the refreshPriority is beter, because you don't know in which your order the site will end up, so if you have a dynamic way to set the refreshPriority, so that they are always in order it will be the most robust. You could check the ScrollTrigger demo pages https://greensock.com/st-demos/ the Greensock YouTube channel https://www.youtube.com/c/GreenSockLearning/videos or our own @Carl's YouTube channel also has a lot of great content. https://www.youtube.com/user/snorklTV/videos4 points
-
Hi @Shahram welcome to the forum! What I would do is create timelines for each animation "open navigation", "shop panel", "blog panel" and "contact panel". Then animate "open navigation" and the menu item that is clicked. Then when clicking on blog check if "open navigation" has already played and reverse the panel that has already been clicked. If the animation "open navigation" has not been clicked it probably means that none of the panel animations has been played. // Person clicks shop, then blog Animate "open navigation Animate "shop panel" // User now clicks blog "open navigation" als already been open Reverse "shop panel" Animate "blog panel" As a side note: is there any reason you're loading GSAP 3.9.1? Where are currently one version 3.11.5 and you're using the old GSAP 2 syntax the GSAP 3 syntax is much easier and more readable check out https://greensock.com/3-migration/4 points
-
So for initial state setting I usually either just use CSS or I use set the initial state outside of a timeline. Then the shutter would be a set tween on a timeline. My animation files usually end up looking like this - set initial state and transform origins up top, then you have a fresh starting point for the timelines. https://codepen.io/GreenSock/pen/xxyBzYd?editors=0010 Although nothing wrong with a small duration tween here either, different strokes for different folks and all.4 points
-
Yeah, a ton of thought has been put into zero-duration tweens (as Cassie said) and they're just inherently tricky because there's literally no distinction between the start and end positions. If the playhead lands directly on top of that spot...is it supposed to render the start or end state? To complicate things further, .from() tweens that immediately render bring a whole different set of challenges - in the vast majority of cases people want from() tweens to render immediately which means the starting state shouldn't get baked into the tween (if it did, anytime the playhead is at a position BEFORE the from() tween, it'd render at that pre-tween state which is almost surely different than the "from" state). Anyway, I'll resist writing 3 pages about all the challenges, why things behave the way they do, and why changing the behavior could cause a lot of other problems...but suffice it to say that you should be able to just use a duration of 0.001 to accomplish your goals (if I understand them correctly).4 points
-
Since the morph already happened on the first tween of the timeline, it appears nothing is morphing for tweens 2 & 3. Easiest solution is to use a .fromto() tween rather than a .to() tween. https://codepen.io/PointC/pen/Jjmzdxp/6382a2db1d9550ba86e6e33f3f318b9a Happy tweening.4 points
-
Hi, This is basically related to the units you're passing to GSAP. So right now you're passing a number 0, so GSAP says: "OK, you want me to tween the width of this element to 0 pixels" and GSAP, being an extremely good library, does exactly what you're asking. The problem is that you're basing your entire setup in percentage-based values. For that you have to be specific so GSAP knows you're intentions. Regardless of all the hard work putted into GSAP, the library still can't read minds . This seems to work the way you intend: walltl .to(".left-crunch", { width: "0%" }) .to(".right-crunch", { width: "0%" }, 0); Hopefully this helps. Happy Tweening!4 points
-
Hello Carl, welcome to the GSAP forum. The main problem is that your CSS is not set up to align the sections beside one another. So you'll want to have another look at the many many examples for fake-horizontal scenarios like that to see how you can get that done - e.g. using flex on your main-container and adjusting everything according to that properly, or alternatively using a display: inline/inline-block setup for your sections. Here is your demo with the main container scaled down to showcase the issue causing your troubles (scroll down a bit to see the problem). https://codepen.io/akapowl/pen/mdzQmeg You can find some examples fake-horizontal setups here... https://greensock.com/st-demos/ ... and this here is one of my demos. https://codepen.io/akapowl/pen/dyvygmj Edit: Here is a rather basic Flex-Layout for your convenience - this one might be a bit easier to wrap your head around. https://codepen.io/akapowl/pen/RweqVKm4 points
-
Hey there @grizhlie It sounds like you are actually looking for svgOrigin - there is no such thing as svgCenter, afaik. https://greensock.com/docs/v3/GSAP/CorePlugins/CSSPlugin#h3-svgorigin I'm not entirely sure why, but even if I set that to "200 200" which is supposed to be the center of your SVG, it doesn't align properly - very likely because of the transforms you have on your moon - so you might want to rework that in your SVG Editor. I do recall, that Affinity Designer v1 had an option to flatten transforms on export; so you might want to look for that option in v2, too - maybe it solves that problem for you. Apart from that, setting the svgOrigin to "180 180", appears to be working fine in your case, though. I hope this will help a bit at least. Happy rotating! https://codepen.io/akapowl/pen/mdzQWyp P.S.: You might also want to consider updating your syntax to the newer v3 syntax (e.g. with regard to durations and eases); although it is still supported, support for the old v2 syntax might get erased in a major future version of GSAP at some point.4 points
-
Hi @AmbrosiaDevelopments and welcome to the GreenSock Forums! I'm not an expert in particle animations and normally they're not the simplest thing to achieve, but for what I can see what you need is just some delay between replays. In your first two examples adding a repeatDelay option to the stagger config seems to work: stagger: { each: 0.05, repeat: -1, repeatDelay: 5, // amount of seconds before it repeats } In your last example maybe this: onComplete: () => gsap.delayedCall(5, () => setCx(dot, delay)) Also you can learn from the masters themselves (@Carl and @OSUblake) https://codepen.io/osublake/pen/BjNZYP Hopefully this helps. Happy Tweening!4 points
-
snap: { textContent: 1 } https://codepen.io/PointC/pen/KKGBXaR/10c8677689d49df47fe1e690eca483cb Happy tweening and thanks for being a club member.4 points
-
You'd need to loop through each line and select the bottom/top .char in those lines and start all tweens at 0. Something like this. https://codepen.io/PointC/pen/OJBwJzd/b300c7bf37ea7a9567e1733d87bbbe30 Just FYI - you had an ease on the timeline itself, but timelines don't have eases. I moved that power4.inOut ease to the defaults for the timeline so it would be applied to each tween. Hopefully that helps. Happy tweening and thanks for being a club member.4 points
-
Does adding this make any difference? #smooth-content { will-change: transform; } Happy tweening.4 points
-
Hi and welcome to the GreenSock forums, Thanks so much for the demo. It definitely helped me experiment with a solution. One way of doing this is to have 2 separate ScrollTriggers. One that pins the hero section and another that animates the bars. In order to do this I had to quickly reparent the bars in another div. I also messed around with some of the position values of the bars and durations slightly. https://codepen.io/snorkltv/pen/RwqNVEX?editors=0100 I'm sure it could use some tweaking, but hopefully you see that a big advantage of this setup is that you can adjust the end position of the pinned hero so that it can detach independent of the bars animating and you can play with the values a bit. Also, it will look better when the window is taller. In the vertically challenged embed above the effect gets a bit lost. For this type of effect there is nothing wrong with using different durations for the bar animations. Someday you may want to look into ScrollSmoother which has some very handy parallax capabilities built in. I'm calling this the Double ScrollTrigger Pin and Parallax. It may come to a CreativeCodingClub.com lesson someday soon3 points
-
Seems like you can't clip-path a video directly, but if you wrap it in an extra div and clip that it does work. I had to move the clip-path to the visible SVG shapes instead of in the refs. But hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/VwVYvJm?editors=10103 points
-
Hey Tom! Just to be clear about why your original solution wasn't working - your calculations with getBoundingClientRect() were assuming that the elements where all in their original positions, but if you refresh when you're further down (part-way into the animation), that wouldn't be the case AFTER the refresh. Those values would be different. So Carl's/Rodrigo's solutions work because it's happening at the proper time when those things are temporarily reverted (part of ScrollTrigger's refresh() involves rolling everything back to the original state with no pinning, going back to a scroll position of 0, etc. just so that everything gets calculated properly, top-down).3 points
-
As stated in your previous topic with the same question pinSpacing: false, is what you could use. From the ScrollTrigger docs check for more info and check the video explaining it Boolean | String - By default, padding will be added to the bottom (or right for horizontal: true) to push other elements down so that when the pinned element gets unpinned, the following content catches up perfectly. Otherwise, things may scroll UNDER the pinned element. You can tell ScrollTrigger not to add any padding by setting pinSpacing: false. If you'd rather it use margin instead of padding, you can set pinSpacing: "margin". Note: pinSpacing works in most cases, but it really depends on the way you set up your DOM and CSS. For example, if you pin something in a parent that has display: flex or position: absolute, the extra padding won't push other elements down/right so you may need to manually space things out. pinSpacing is just a convenience that works in most situations. Important: if the container is display: flex, pinSpacing is set to false by default because that's typically what is desired since padding works differently in that context. Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/ZEmEMKG?editors=10103 points
-
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. https://codepen.io/snorkltv/pen/BaGBYoo?editors=1111 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.3 points
-
3 points
-
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 https://codepen.io/snorkltv/pen/ExdBrYO 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.3 points
-
Oooh fun one. you could make a tween for the ticker and then animate the progress? I've got to crack on with some other stuff, but maybe something like this could be a starting point? https://codepen.io/GreenSock/pen/eYPwZZb?editors=10113 points
-
@mvaneijgen Thanks again for your help, advice and links, I really appreciate it. Yes, I've paid for a subscription for snorklTv and can't recommend it enough. Time to do some scrollTrigger nerding out! Thanks again3 points
-
Oh wow, that's so much simpler than anything I was trying to do. I changed my .npmrc to that and added my Greensock Club token as NPM_TOKEN at the env var section of Vercel, and that's that. Thank you so much!3 points
-
I recently got acquainted with GSAP and I can confidently say that it has really made my work easier and more professional. Thank you very much GreenSock team ✌️3 points
-
Heya! Maybe you need to wait for your custom font to load? Give this a pop - document.fonts.ready.then(function () { // do the thingsss });3 points
-
Hi, Be sure to have something like this in your .npmrc file: always-auth=true @gsap:registry=https://npm.greensock.com //npm.greensock.com/:_authToken=${NPM_TOKEN} This repo was deployed less than two weeks ago to vercel without any issues: https://github.com/rhernandog/gsap-bonus-npm-vercel Here is the live page (not a lot, just a proof of concept of a successful deployment and CI/CD pipeline): https://gsap-bonus-npm-vercel.vercel.app/ If you inspect the console you'll find this line there: https://github.com/rhernandog/gsap-bonus-npm-vercel/blob/main/pages/_app.js#L8 Hopefully this helps. Happy Tweening!3 points
-
Definitely, There's a lot to explain here. Viewport heights and height measurements/pinning in general is quite tricky on mobile because of the browser resizing. That's why we have different viewport units now. https://www.bram.us/2021/07/08/the-large-small-and-dynamic-viewports/#large-viewport And ignoreMobileResize https://greensock.com/docs/v3/Plugins/ScrollTrigger/static.config() --- Bearing that in mind, not all solutions that work for desktop work for mobile. Which is a ok because we have media queries and matchMedia to utilise. https://greensock.com/docs/v3/GSAP/gsap.matchMedia() Before rolling a solution, it's also worth mentioning that this solution is specific to ScrollSmoother, where there are limitations around position fixed, it also looks like this user had markup limitations too. If you don't have markup limitations and you're not using ScrollSmoother, then this isn't the right solution for you. You don't even need GSAP for this, you can just do it with CSS https://css-tricks.com/the-slideout-footer/ Hope this helps. If the above solution doesn't work for you for some reason, let me know and we can see how best to achieve it with GSAP. Good luck!3 points
-
You're are animating to something and the next time you animate to the exact same point, so nothing will happen because it already is at its end position. What I would do is create a timeline, with the repeats and the repeat delays build in, this way you don't need to repeat your code. If you do want to change your animation each time, but have the same end point you could also use a .fromTo() animation to ensure it always starts from the beginning. Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/KKGEEoW?editors=00103 points
-
Can you share what you've tried already? We love to see minimal demo's, that way we can see your thought process and thus better help you. Try creating a minimal demo of what you're trying to do, this has two benefits. First this allows you to experiment and try out new ideas, second, you have an easy version you can share in which anyone could edit and modify the code.3 points
-
I would create a loop for each element you wan two have a trigger for and then add the logic for each item in the loop. Your example also forgot to load ScrollTrigger and personally I like to split my ScrollTrigger logic from the animation, so that is why I've created a timeline for each element. Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/LYgqGOR?editors=10103 points
-
Hi @Rodrigo! You know, I was actually already starting to think on how I could move the circle element to be inside the button itself after the pinning ends, but the task seemed pretty daunting. I had no idea Flip existed. That's amazing! That's exactly what I needed, thank you so much. For any other brave souls stumbling on a similar problem, I've updated my codepen to use Flip and it works like a charm.3 points
-
Ok nevermind, I've answered my own question. Conceptually what I was doing was WRONG. I had to do all those workarounds because I had set a pinnedContainer and set the pin itself to a defined container. By simply chaning pin to true, then everything is lining up correctly and problems are solved3 points
-
Hi there, I think the question here is down to the starting positions of elements with data-speed added on a ScrollSmoother page If I'm right we have a solution coming in the next release https://codepen.io/GreenSock/pen/gOBedNX ScrollSmoother is a Club GreenSock plugin, and there's no membership listed with this account. Is the membership associated with a work account? If so you'll be able to download the newest files from that account dashboard after we release them3 points
-
y transforms with the element you're using as the trigger can be a little confusing. Especially with two ScrollTriggers on the same element. IMHO it would probably be easiest to use a parent element around your .events and use that as the trigger. That way you're not animating the actual trigger element. Something like this should work. https://codepen.io/PointC/pen/VwEGVLK Hopefully that helps. Happy tweening.3 points
-
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 https://codepen.io/snorkltv/pen/NWOBJde?editors=0011 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.3 points
-
Hi there - We're happy to nudge in the right direction but we don't have the time to recreate work, or more importantly the permission to copy the work from the original code authors. The 'curtains' look to be largely down to masking and the ease is likely expo.out, or a custom ease with a similar curve. If you search for masking in the forums you'll get plenty of hits!3 points
-
If I understand your goal correctly, it would be best to make the body the trigger. https://codepen.io/PointC/pen/OJBwxpg/4cfca8354a6819dacdba464b376353af Hopefully that helps. Happy tweening.3 points
-
Yep, @PointC is exactly right. Here's a slightly different way to structure it (not necessarily any better): https://codepen.io/GreenSock/pen/wvYxaMq?editors=00103 points
-
What I expected was for the animation to repeat fluently without delays, but apparently I used 'start' wrong. Or rather the timing of it. When I used this: tl.set('#red', {y:75}, 'start'); tl.to('#red', {y:150, duration:1}, 'start+=1'); tl.to('#red', {y:0, duration:1}, 'start+=3'); tl.to('#red', {y:75, duration:1}, 'start+=5') It worked like I expected. With 1 second between each frame and when it repeats it starts with that same 1 second delay. In my first code it appears like somehow an extra second was added before the start of the repeat, but what was because of that start+=1 in the first tween (while the other 2 tweens followed up on each other directly without a 1 second pause). So that is solved.3 points
-
That was a nice read. I think it deserved a reply: thank you! Lately I've mostly been working with React, and there's a big temptation to switch to something like Framer Motion, which is built for such frameworks. But this afternoon I was trying to accomplish something with both libraries to see which one would get me there faster. I definitely appreciate your great tutorials that are so clear and easy to digest, thanks to them I managed to achieve my goal much faster. Your great learning materials and the forums make a big difference when deciding to pick an animation library. Again, just wanted to say thanks!3 points
-
The clip-path isn't working in your demo because it isn't applied to the group holding the image. Line 9 of the HTML needs to be: <g clip-path="url(#mask)"> Happy tweening.3 points
-
Our own @OSUblake has a few examples that should put you on the right path. https://codepen.io/osublake/pen/mEpado https://codepen.io/osublake/pen/ezyyzG https://codepen.io/osublake/pen/reQdrN Happy tweening.3 points