Leaderboard
Popular Content
Showing content with the highest reputation since 06/12/2025 in all areas
-
I was looking for a way to create a speech bubble cutout, like in the design you can see below. If you pay close attention to you can see that the blue arrow doesn't blend in perfectly and that is the exact problem I’m trying to solve! I was going down all kinds of avenues to make this dynamic, you can see that currently the cutout is below the logo text, but what If I want to have it in the middle of the screen or move the logo somewhere else than I would have need to create all kinds of cutouts to make this work and then even more for more screen sizes! That would not work, so my first thought process would be to figure out what the SVG path would look like and then figure out what values to dynamically update specific values to have the cutout be able to move along the x-axis. In the end what I’d figured out was so simple that I had to share this with you folks! Dynamically updating the SVG path would work, but I couldn't figure out which values to update, there are probably SVG wizards 🧙 out there for whom this is trivial, but sadly I’m not one of them, but going down that route made me come to my solution! What if I let GSAP figure it out for me! When I was trying to figure out what updated in the SVG path I had exported one version where the arrow was all the way left and all the way right, below are the paths maybe you’re one of that wizards that could easily see what needs to be dynamic in this path // Left M7.248,24l-7.248,0l0,-24l1920.11,0l0,24l-1862.86,0l-17.921,-17.188c-3.909,-3.749 -10.248,-3.749 -14.158,-0l-17.921,17.188Z // Right M1864.08,24l-1864.08,0l0,-24l1920.11,0l0,24l-6.029,0l-17.922,-17.188c-3.909,-3.749 -10.248,-3.749 -14.157,-0l-17.921,17.188Z But even than that would require a lot of code to make it dynamic and the solution below is so simple that it has my preference anyway. https://codepen.io/mvaneijgen/pen/ogXrvrJ See how little code this is! We just tween between the two paths and GSAP does all the heavy lifting for us. Ok, I now hear you think, big whoop it is animating from left to right, but you want it to stay below a logo… ha, that is what so clever about it, although GSAP is great for animating things it doesn't have to animate it, in the new above there is a bit of code commented out that sets the current tween to .progress(0.5) and thus the cutout lines up in the middle! How easy is this. Some quick tips! Mainly for myself, because I will probably find my own post in a year or two to read how I solved some issue (ever had this happen your self?) When exporting the path out of your preferred vector program (mine is Affinity Designer) make sure the cutout is a bit away from the edge, if you don't do this (my program) merges the point that are on top of each other and thus this will result in different paths, which than will not look correct when animating between them. Currently my setup is a bit extreme you probably could get a way with any distance between the to points, as long as they don't merge while exporting This can also be done with MorphSVG, so it is up to you what you prefer4 points
-
The solution to this is adding smoother.effects('[data-speed], [data-lag]'); to the afterNavigate() in svelte in your +layout.svelte.3 points
-
Hi @Heo welcome to the forum! Your .h2 is not the parent element of the text, I you split on the <p> which is the parent element with all the text it works as expected. Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/pvJBRjV3 points
-
@mvaneijgen kicks back all fancy2 points
-
Hi, Just call the refresh method before setting the new scroll position: onLeave(self) { let scroll = lenis.scroll, pinDistance = self.end - self.start; self.kill(true, true); scrollTextSecond.progress(1); // Call the refresh method ScrollTrigger.refresh(); lenis.scrollTo(scroll - pinDistance, { immediate: true }); } https://gsap.com/docs/v3/Plugins/ScrollTrigger/static.refresh() That will update the calculations ScrollTrigger makes and set the start/end points of the remaining ScrollTrigger instances according to the updated height of the DOM. The issue here is that when you remove the first ScrollTrigger instance the height of the document is updated because the pin space generated is removed, but the next ScrollTrigger instances don't know about that, so the calculations made, when the pin space was present in the document, are no longer accurate. Hopefully this clear things up Happy Tweening!2 points
-
I assume you're trying to do this?: https://codepen.io/GreenSock/pen/dPYbdZR?editors=00102 points
-
To fix the iPhone scroll jitter after applying 'normalizeScroll(true)', add the css property 'will-change: transform;' to the jittering element. That fixed the issue for me.2 points
-
Looks like you're doing two things here 1) Splitting before the fonts are loaded and not re-splitting on resize (With lines you can use the new onSplit functionality to maintain responsivity) 2) Creating masks manually (You can do this in splittext) https://codepen.io/GreenSock/pen/OPyLjMX?editors=0110 Hope this helps, this video walks through it too2 points
-
Hi, This has nothing to do with ScrollTrigger itself but with the start/end points you have for each section. Right now you're creating a ScrollTrigger for the animation for each section and an extra ScrollTrigger for the section that gets pinned, because the start and end points of the ScrollTrigger for the animation doesn't match the ones for the one that creates the pin, you think that there is some extra space, but is just that the end points are different so the element is pinned when scrolling up before the onEnterBack callback is called. Here is a fork of your demo that shows that: https://codepen.io/GreenSock/pen/LEVwwdV Maybe is best to use a different configuration in the loop in order to create animations and the pinning, maybe something like this: https://codepen.io/GreenSock/pen/NPqQQBY Hopefully this helps Happy Tweening!2 points
-
Hi @jovenfabuloso welcome to the forum! Check out this topic where a lot is being disced about video encoding, ect. I would also set scrub: true, instead of adding a delay to the scrub that way everthing is direct Hope it helps and happy tweening!2 points
-
Hi @John Henry welcome to the forum! What have you tried already? Would love to see, so that we can better understand your thought process and see how we can better nudge you in the right direction. Currently the is no GSAP code in your demo and it also loads no GSAP plugins at all. My advise would be start small and just make something work and then slowly build it out from there. Keep forking your work, so you can test out different ideas you have. The most simple step I could think of is just create a ScrollTrigger and pin your shape. If you can login to Codepen again here is a starter template which loads all the plugins https://codepen.io/GreenSock/pen/aYYOdN Hope it helps and happy tweening!2 points
-
When working with SVG's and GSAP the most important part is constructing your SVG's. This blog post by our own @PointC always helps me https://www.motiontricks.com/organic-morphing-getting-needed-points-from-adobe-illustrator/ There is nothing that makes this inherently difficult with GSAP except for the fact that wavify has figured out all the logic for you already and now you have to manually (or at least with your own logic) create this yourself. Just for your information GSAP doesn't draw anything, it just interpets numbers and strings and tween between those values, so if you tween between the same point coordinates as wavify then it will look the exact same. The only issue now is that you have to create those assets/paths by hand or figure out some other logic. This can also be a handy tool to debug/figure out how your paths are constructed https://yqnn.github.io/svg-path-editor/ Hope it helps and happy tweening!2 points
-
Hi @Frankievzzly welcome to the forum! I've loaded the GSAP plugins in to your pen and then everything seems to work as expected https://codepen.io/mvaneijgen/pen/OPVYgEg?editors=0010 It looks like you're using really old GSAP code from version 2 we are currently on GSAP version 3+, so highly recommend updating the code to use the latest syntax, then the docs will also make a lot more sense and easier to use https://gsap.com/resources/3-migration Also SplitText just had a mayor update which makes it easier to use and write, check it out https://gsap.com/docs/v3/Plugins/SplitText/ Sound fine to me! You can also check out the docs for some other tips, but if it works it works! https://gsap.com/resources/Wordpress Hope it helps and happy tweening! Edit: and if you want to use ScrollTrigger https://gsap.com/docs/v3/Plugins/ScrollTrigger/ just add ScrollTrigger to your timeline and you're golden! https://codepen.io/mvaneijgen/pen/EajzXeB?editors=00102 points
-
Hi @studiowai welcome to the forum! Check out FOUC (flash of unstyled content) https://gsap.com/resources/fouc/ It is as easy as setting visibility: hidden; to the elements you want to hide on page load and then using a .set() with autoAlpha: 1 when your GSAP code is ready. Hope it helps and happy tweening!2 points
-
Hi Niazy! I'm obviously not the gsap team, but thought I'd try and help get you a reply - they're 100% going to ask for a small demo to try and understand what you want to achieve. Starter demos can be found here2 points
-
for a simplified version for the black and white imgs in the background as you asking i think you can start here tweaking the duration and using dynamic function to add all the imgs, ofc if you can work with canvas i think it will be better specially if you have a lot of imgs , also you can start watching for scroll or drag events and using that velocity to animate them left and right like the reference you shared https://codepen.io/ahmed-attia/pen/qEEjqoZ?editors=00102 points
-
quick and dirty, but i tried porting horizontalLoop helper to typescript 😄 export function horizontalLoop( items_: string | object | Element | null, config: { repeat?: number; paused?: boolean; speed?: number; snap?: number | false; paddingRight?: number; reversed?: boolean; } = {}, ) { const items = gsap.utils.toArray(items_) as HTMLDivElement[]; const tl = gsap.timeline({ repeat: config.repeat, paused: config.paused, defaults: { ease: "none" }, onReverseComplete: () => { tl.totalTime(tl.rawTime() + tl.duration() * 100); }, }); const length = items.length; const startX = items[0].offsetLeft; const times: number[] = []; const widths: number[] = []; const xPercents: number[] = []; let curIndex = 0; const pixelsPerSecond = (config.speed || 1) * 100; const snap = config.snap === false ? (v: number) => v : gsap.utils.snap(config.snap || 1); // some browsers shift by a pixel to accommodate flex layouts, so for example if width is 20% the first element's width might be 242px, and the next 243px, alternating back and forth. So we snap to 5 percentage points to make things look more natural let curX; let distanceToStart; let distanceToLoop; let item; let i; gsap.set(items, { // convert "x" to "xPercent" to make things responsive, and populate the widths/xPercents Arrays to make lookups faster. xPercent: (i, el) => { const w = (widths[i] = parseFloat( gsap.getProperty(el, "width", "px") as string, )); xPercents[i] = snap( (parseFloat(gsap.getProperty(el, "x", "px") as string) / w) * 100 + (gsap.getProperty(el, "xPercent") as number), ); return xPercents[i]; }, }); gsap.set(items, { x: 0 }); const totalWidth = items[length - 1].offsetLeft + (xPercents[length - 1] / 100) * widths[length - 1] - startX + items[length - 1].offsetWidth * (gsap.getProperty(items[length - 1], "scaleX") as number) + (config.paddingRight ?? 0); for (i = 0; i < length; i++) { item = items[i]; curX = (xPercents[i] / 100) * widths[i]; distanceToStart = item.offsetLeft + curX - startX; distanceToLoop = distanceToStart + widths[i] * (gsap.getProperty(item, "scaleX") as number); tl.to( item, { xPercent: snap(((curX - distanceToLoop) / widths[i]) * 100), duration: distanceToLoop / pixelsPerSecond, }, 0, ) .fromTo( item, { xPercent: snap( ((curX - distanceToLoop + totalWidth) / widths[i]) * 100, ), }, { xPercent: xPercents[i], duration: (curX - distanceToLoop + totalWidth - curX) / pixelsPerSecond, immediateRender: false, }, distanceToLoop / pixelsPerSecond, ) .add("label" + i, distanceToStart / pixelsPerSecond); times[i] = distanceToStart / pixelsPerSecond; } type Vars = { overwrite?: boolean; modifiers?: { time?: (index: number) => number; }; }; function toIndex(index: number, vars: Vars = {}) { if (Math.abs(index - curIndex) > length / 2) { index += index > curIndex ? -length : length; // always go in the shortest direction } const newIndex = gsap.utils.wrap(0, length, index); let time = times[newIndex]; if (time > tl.time() !== index > curIndex) { // if we're wrapping the timeline's playhead, make the proper adjustments vars.modifiers = { time: gsap.utils.wrap(0, tl.duration()) }; time += tl.duration() * (index > curIndex ? 1 : -1); } curIndex = newIndex; vars.overwrite = true; return tl.tweenTo(time, vars); } tl.progress(1, true).progress(0, true); // pre-render for performance if (config.reversed) { tl.vars.onReverseComplete?.(); tl.reverse(); } const extra = { next: (vars: Vars) => toIndex(curIndex + 1, vars), previous: (vars: Vars) => toIndex(curIndex - 1, vars), current: () => curIndex, toIndex: (index: number, vars: Vars) => toIndex(index, vars), times: times, }; return Object.assign(tl, extra); }1 point
-
This is SO COOL. What a fun solution!!1 point
-
Check out the migration guide on the docs https://gsap.com/resources/3-migration Hope it helps and happy tweening!1 point
-
Hey! I am Lucas, a full-stack dev that has been working with GSAP and 3D graphics for almost four years now. My portfolio was featured on the GSAP official showcase back in December 2023 and I also submitted my latest project. You can check it out first-hand here: https://gilneas-bank.lucaslamonier.com/ In this website you can travel to different universes to learn more about a currency bot for Discord. Beyond front end I also do: back end: Node.js, Next.js databases: MySQL, MongoDB, Google Clooud's Datastore hard surface modelling and basic animations in Blender Unreal Engine bots for Discord and more! If you have a cool idea or an interesting project going, reach out! Maybe we can do something awesome together! [email protected] https://www.lucaslamonier.com/1 point
-
Check out the ease visualizer https://gsap.com/docs/v3/Eases/CustomEase/#description you're probably lookin for the elastic.out and "elastic.out(2, 0.75)" seems like some nice values. Note for this your duration needs to be a bit longer. Another note, currently on click you create a new timeline (and all the tweens) each time you click this is not inherently wrong, but it is good to know that you are doing it. My preferred setup is to just create a timeline (outside of the click) and then inside the click just .play() or .reverse() that one timeline. Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/ZYGgMYR?editors=00101 point
-
Hi, The main issue is the fact that, while the duration and ease are the same one is triggered a bit after the other here: animation.play(); gsap.to(".pin-target > .inner", { y: 100, ease: "none", duration: 0.24 }); The Timeline instance called animation, is played immediately but for the other Tween GSAP has to traverse the DOM in order to get the element with that particular selector and then create the animation, that takes a few milliseconds to happen, hence the delay between both. You can create a Tween/Timeline for the ".pin-target > .inner" element and then play/reverse it in the same way you do with the animation instance. In that case there is no delay, as shown in this fork of your demo: https://codepen.io/GreenSock/pen/myJZRZO Hopefully this helps Happy Tweening!1 point
-
I see, you use scrub to shorten the duration of the animation and reproduce it. Thanks for the reference!1 point
-
Hi, A few things: There are several missing closing tags in your HTML You don't have a proper wrapper and content elements setup in your HTML and you're not passing that into ScrollSmoother's configuration as mentioned here: https://gsap.com/docs/v3/Plugins/ScrollSmoother/#setup A long smooth time means that the element with the content will catch up with the scroll position very slowly, especially at the end of the motion, which can create some sub-pixel rendering of certain elements (stemming from decimal values in the transform applied to the content element). It might be a good idea to use a smaller value. You can use will-change: transform in the smooth-content element in order to have a better experience. Here is a fork of your demo: https://codepen.io/GreenSock/pen/WbvBwRQ Hopefully this helps Happy Tweening!1 point
-
Hi, My first attempt at something like the video you posted would be image parallax and Clip Path as shown in these demos: https://codepen.io/GreenSock/pen/azoGmbz https://codepen.io/GreenSock/pen/qEEvRQz https://codepen.io/GreenSock/pen/WNmeyRO Hopefully this helps Happy Tweening!1 point
-
Be careful about doing that because if you're creating GSAP-related stuff inside that requestAnimationFrame() handler, those won't get cleaned up properly unless you wrap it in a contextSafe() because that doesn't get called DURING the execution of the useGSAP() hook (it gets called 1 tick later, thus those things don't get recorded with the context). // BAD (not context-safe): useGSAP(() => { requestAnimationFrame(() => { gsap.to(...); // not created while the useGSAP() is executing, so immune from cleanup }); }); // GOOD useGSAP((self, contextSafe) => { requestAnimationFrame(contextSafe(() => { gsap.to(...); // gets cleaned up properly because it's context-safe })); });1 point
-
@Kanso please read the following info on the docs https://gsap.com/resources/fouc/ You indeed set visibility: hidden; in your CSS and then autoAlpha: 1 in your GSAP .set() If you are still struggling with the setup please provide a minimal demo with your code in action, than we can help you debug Hope it helps and happy tweening!1 point
-
I'm silly. Needed to import the codepen css file: > import "https://codepen.io/GreenSock/pen/xxmzBrw/fcaef74061bb7a76e5263dfc076c363e.css" See: https://svelte.dev/playground/bb916b13ad75423db361f078fa09aa4d?version=5.34.91 point
-
Hey Nick, Really hard to see without a minimal demo, but this demo seems to report the same height for both elements: https://codepen.io/GreenSock/pen/vEOPadm Hopefully this helps Happy Tweening!1 point
-
Wow, it's amazing how much simpler that is than my original code. It's almost a shame because I was adapting code from a useful source/guide, but they obviously over complicated things. I guess it's still a good source of learning to try and adapt their work to a simpler approach in the future. I'm going to have a play around with it and try and add a few other animations to the cards, but on first glance that makes things much easier, thanks! Appreciate it!1 point
-
Hi @Kamran Ali and welcome to the GSAP Forums! That effect most likely is being done with WebGL (THREEJS) and GLSL Shaders: https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_on_the_web/GLSL_Shaders https://thebookofshaders.com/ One alternative is to use the MorphSVG Plugin as shown in this thread: Also in these demos by @PointC and @OSUblake https://codepen.io/PointC/pen/BYRavx https://codepen.io/osublake/pen/BYwgBg Also I see you're using React, proper cleanup is very important with frameworks, but especially with React. React 18 runs in strict mode locally by default which causes your useEffect() and useLayoutEffect() to get called TWICE. Since GSAP 3.12, we have the useGSAP() hook (the NPM package is here) that simplifies creating and cleaning up animations in React (including Next, Remix, etc). It's a drop-in replacement for useEffect()/useLayoutEffect(). All the GSAP-related objects (animations, ScrollTriggers, etc.) created while the function executes get collected and then reverted when the hook gets torn down. Here is how it works: const container = useRef(); // the root level element of your component (for scoping selector text which is optional) useGSAP(() => { // gsap code here... }, { dependencies: [endX], scope: container }); // config object offers maximum flexibility Or if you prefer, you can use the same method signature as useEffect(): useGSAP(() => { // gsap code here... }, [endX]); // simple dependency Array setup like useEffect() This pattern follows React's best practices. We strongly recommend reading the React guide we've put together at https://gsap.com/resources/React/ If you still need help, here's a React starter template that you can fork to create a minimal demo illustrating whatever issue you're running into. Post a link to your fork back here and we'd be happy to take a peek and answer any GSAP-related questions you have. Just use simple colored <div> elements in your demo; no need to recreate your whole project with client artwork, etc. The simpler the better. Hopefully this helps Happy Tweening!1 point
-
that's great point! I haven't even thought about it! Now it works fine. Thank you!1 point
-
hi sohil , sorry i got lost with the names in the project , also not sure why you have scrollto plugin since you are using scrollsmoother , but maybe if you check these pens they can help you understanding how navigation works https://codepen.io/GreenSock/pen/KKXZOyZ?editors=1010 https://codepen.io/GreenSock/pen/xxjErmp https://codepen.io/GreenSock/pen/wvrXRdZ1 point
-
@Kanso it's very difficult to troubleshoot; without a working demo. Try setting up a codepen to explain where you are up to. Here is a handy starter https://codepen.io/GreenSock/pen/aYYOdN1 point
-
Hi @Arthur J and welcome to the GSAP Forums! The best place to start is the Installation section of our Learning Center, more specifically the Webflow part: https://gsap.com/resources/Webflow Just in case here is a simple demo: https://preview.webflow.com/preview/word-loop-width?utm_medium=preview_link&utm_source=designer&utm_content=word-loop-width&preview=35c04d74b129a97ee6f8a11d1c221126&workflow=preview Here is the live preview: https://word-loop-width.webflow.io/ Here is the codepen it's based on: https://codepen.io/GreenSock/pen/jOgYqwW Hopefully this helps Happy Tweening!1 point
-
Hi, You can use GSAP MatchMedia for this: https://gsap.com/docs/v3/GSAP/gsap.matchMedia() Here is a similar demo: https://codepen.io/GreenSock/pen/wvZqwyg Hopefully this helps Happy Tweening!1 point
-
Good work! Looks really nice 🥳 Thanks for sharing! 💚1 point
-
Thanks for letting us know. The problem is caused by the fact that you can't have an animation along a path that has fewer than 2 anchors. That's not a valid motion path. In the next release, we'll add a console.warn() about that instead of throwing errors.1 point
-
Hi Rodrigo, this is exactly what I am looking for, thank you!1 point
-
Hi, In your demo there is no <main> tag so all these selectors return an empty Nodelist: if (window.innerWidth > 540) { tl.set(document.querySelectorAll("main .loaded-in"), { y: "50vh", }); } else { tl.set(document.querySelectorAll("main .loaded-in"), { y: "10vh" }); } tl.to(document.querySelectorAll("main .loaded-in"), { duration: 1.5, y: "0vh", stagger: 0.07, ease: "expo.out", clearProps: true }, "-=0.9"); GSAP is actually telling you that in the console: GSAP target [object NodeList] not found. console.log(document.querySelectorAll("main .loaded-in")); // NodeList [] Please be sure your demo clearly illustrates the issue you're having in order to offer you the best possible support 🙏1 point
-
Seeing as GSAP now went free (Thanks to webflow) it might be an idea to have Google update their Studio CDN to include the newly freed plugins, and update their GSAP version, it looks like it's about 2 years out of date by now: https://support.google.com/richmedia/answer/6307288?hl=en&sjid=15605899940228504708-EU Does the GSAP team have any Google contacts they can leverage for that? or how have updates worked in the past?1 point
-
Hi, Indeed the return callback on the onMount hook is the way to do it, using GSAP Context in order to grab all your GSAP instances in it and make cleaning up super easier: https://gsap.com/docs/v3/GSAP/gsap.context() https://svelte.dev/docs/svelte/lifecycle-hooks#onMount let ctx; onMount(() => { ctx = gsap.context(() => { // Add all your GSAP instances here }); return () => ctx && ctx.revert(); // Easy cleanup! }); You can check this demo in order to see it in action: https://stackblitz.com/edit/sveltejs-kit-template-default-unljf6?file=src%2Froutes%2F%2Bpage.svelte Hopefully this helps Happy Tweening!1 point
-
Hey, after a bit of thinking I have a solution that also might help others, searching around I figured that the Three.js objects use Euler angles, but by using Quaternons the object actually takes the shortest path to rotate, it's not as simple as tweening the rotation with gsap but it's not too complicate. I first set the quaternions of the object to (0, 0, 0, 1) just to be sure (yes quaternion has actually 4 values, the last one called "w", a factor needed to use quaternions) like this: obj.quaternion.set(0,0,0,1) This was because I wanted my object to go from (0, 0, 0) rotation to another one, if for example you want your object to go from (90, 0, 180) to another one, then you should set those rotations at the beginning. I strongly suggest to use the function below in this case because I don't know how the w factor behaves. If you want an example on how to combine the function below and set the quaternions to (90, 0, 180) for example here's one, to understand at best what I'm doing go see what the function EulQuat.eul_to_quat() is doing below: const initialRotations = EulQuat.eul_to_quat(90, 0, 180); obj.quaternion.set(initialRotations.x, initialRotations.y, initialRotations.z, initialRotations.w); Anyways, then I created an object called "progress" which contains a property called "t" which will be animated from 0 to 1 every time I want to tween the rotation: const progress = { // Progress for animating quaternions t: 0, } I created then a function to help me convert Euler angles to Quaternions easily: const EulQuat = { // Object to contain I created to contain useful function I may need in the future (not needed) eul_to_quat: (x, y, z) => { // Euler to Quaternion angle converter, needed const quat = new THREE.Quaternion(); const eul = new THREE.Euler(degToRad(x), degToRad(y), degToRad(z)); return quat.setFromEuler(eul); }, } Lastly I need to use this setup with gsap to animate the quaternions and the object will take the shortest path when rotating: const tl = gsap.timeline(); // Should be working fine also by just using gsap to animate, I preferred to use a timeline tl.fromTo(progress, { t: 0, // Setting t always to 0 before starting the animation }, { t: 1, // Animating t to 1 scrollTrigger: { trigger: '.your-trigger', start: 'top top', end: 'bottom bottom', scrub: 1, // I always worked with scrub, should be working fine even if scrub isn't enabled immediateRender: false, // To keep animation from glitching if there was a previous rotation }, onUpdate: () => { obj.quaternion.slerpQuaternions( // Using slerpQuaternions() built in function of Object3D Quaternion EulQuad.eul_to_quad(-90, 0, 90), // Starting quaternion position [THIS IS AN EXAMPLE] EulQuad.eul_to_quad(-47, 7.5, -155.2), // Ending quaternion position [THIS IS AN EXAMPLE] progress.t // Progress t that gets animated ) }, }) After that everything should be working fine, enjoy your rotation!1 point
-
Hi, That demo uses ScrollTrigger's observe which has been ported into the Observer Plugin: https://gsap.com/docs/v3/Plugins/Observer/ Here are a couple of demos that show how to integrate ScrollTrigger and Observer: https://codepen.io/GreenSock/pen/ExEOeJQ https://codepen.io/GreenSock/pen/oNdNLxL Hopefully this helps. Happy Tweening!1 point
-
I've been loving this combination so far. If someone is looking to combine the two, hopefully, they come across this post.1 point
-
Hey, There are already a few questions that go in a similar direction. The effect you are looking for is called "ripple" if I am not mistaken. Here are a few of them (just search for "ripple" and select "all content"): There are also some codepens that have this kind of effect, without gsap. https://codepen.io/aspeddro/pen/wGWbEg https://codepen.io/PezCoder/pen/dMyQEy?editors=0010 https://codepen.io/Shyam-Chen/pen/qdQPoL https://codepen.io/thepuskar/pen/eYgyyBb Hope this helps and serves as a good starting point.1 point
-
There isn't really a way to target a specific :after it seems with the CSSrulePlugin. I would advise to just make an extra div and animate that. Here is your pen with some tweaks and my attempts at scoping the :after element, but with no luck. I did how ever update your GSAP tools to their latest version. https://codepen.io/mvaneijgen/pen/eYKPdov?editors=00111 point
-
Hi @kodralex Here's a fork of your demo that should work for you. I switched the ease to none as I find that a bit better with scrub and I boosted the stagger just to make it obvious that everything was working. https://codepen.io/PointC/pen/5e391b2175d6cd57b6dbfd9a870de42e Hopefully that helps. Happy tweening.1 point
-
It is css property 'transform-origin'. // You can set it on current Tween TweenMax.to('.slide', 1, {rotation: '+=360', repeat: -1, transformOrigin: '0% 100%'}); // Or you can set transformOrigin using set externally, // which basically shows that if you change origin once // it will affect all tweens on that element not just for 1 particular tween TweenMax.set('.slide', {transformOrigin: '100% 100%'}); TweenMax.to('.slide', 1, {rotation: '+=360', repeat: -1});1 point