Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...

Leaderboard

Popular Content

Showing content with the highest reputation since 09/20/2021 in all areas

  1. Looping back with a codepen. ✨ https://codepen.io/cassie-codes/pen/zYdxopE
    8 points
  2. Hi and welcome to the GreenSock forums, thanks for providing the demo. it seems your animation is set up to start with the menu open and then close it. I forced the animation to it's end (closed state) using progress(1) at the end of the timeline. it also seems your css is set up so that the page loads with the menu items visible. I set the opacity to 0 in the css and toggle it back to 1 once the page is loaded using gsap.set(".menu-overlay", {opacity:1}) https://codepen.io/snorkltv/pen/PojVQLv?editors=0110
    7 points
  3. Hi there Jenda, Welcome. ☺️ I'm not quite certain what you were trying to achieve with your first loop? Looks like you're looping through multiple containers but pinning the main one? I've removed that until you can tell me what your goal was! Here's a simplified loop pinning the numbers, is that what you were looking for? Positioning the first number would be down to styling things differently and pinning it for the duration - but again, I wasn't really sure what you were after. Hopefully this helps! https://codepen.io/GreenSock/pen/yLoYbpL
    6 points
  4. Hi and welcome to the GreenSock forums, Thanks so much for the clear demo. You can use an onComplete callback to apply clearProp:"all" to remove the inline styles. Be sure to inspect your box after the animation runs in the demo below https://codepen.io/snorkltv/pen/bGrVwxv?editors=1010 more on clearProps: https://greensock.com/docs/v3/GSAP/CorePlugins/CSSPlugin#h3-clearprops this video on callbacks and scope may help too
    6 points
  5. Hi Josh! Performance is very complicated topic as every situation is unique, so I don't have a silver bullet for you. Just from cursory glance at your code, here are some things that might help. First, maybe SVG isn't the best medium to use. SVG is slower than HTML, which is slower than canvas, which is slower than WebGL. If I have to animate hundreds of objects, I'm probably going to reach for canvas or WebGL first. PixiJS is good 2D WebGL renderer. You're also doing way too much work in your mouseover handler, and mousemove might be a better event to use. Notice in this demo how most of the work is done in the ticker function. The mouse handler just records where the mouse position is. https://codepen.io/GreenSock/pen/WNNNBpo Also in your mouse handler, you're creating 692 tweens, which is going to kill performance. You should only create a tween if you need to animate it. This might be easier if you made an object for every one of your polygons. I like to use class objects for this kind of stuff. Some pseudo code. const mapRange = gsap.utils.mapRange(0, 60, 1.2, 0.2); class Polygon { constructor(element) { this.element = element; this.getProp = gsap.getProperty(element); gsap.set(element, { transformOrigin: "50% 50%" }); } update(mouse) { const dist = ...; if (dist < 60) { gsap.to(this.element, { scale: mapRange(dist) }); } else if (this.getProp("scale") < 1) { gsap.to(this.element, { scale: 1 }); } } } const mouse = { x: 100, y: 100 }; const polys = gsap.utils.toArray("polygon").map(el => new Polygon(el)); gsap.ticker.add(() => { for (let i = 0; i < polys.length; i++) { polys[i].update(mouse); } }); Further optimization might involve only calculating if the element is within a set radius of the mouse. Using Math.sqrt() can be an expensive operation if you have to do a bunch of them. You can easily eliminate elements that are outside of the radius like this. // assumes x and y are the center of the element const dx = Math.abs(mouse.x - this.getProp("x")); const dy = Math.abs(mouse.y - this.getProp("y")); if (dx > 60 || dy > 60) { // not inside // check if we need scale to 1 animation needed if (this.getProp("scale") < 1) { gsap.to(this.element, { scale: 1 }); } } else { // calculate distance const dist = Math.sqrt(dx * dx + dy * dy); if (dist > 60 && this.getProp("scale") < 1) { gsap.to(this.element, { scale: 1 }); } else { gsap.to(this.element, { scale: mapRange(dist) }); } } You're also creating a mouse event for each polygon. It would be better to just have single event listener, and then figure out if the mouse is near a polygon. Yes, it requires a lot more work, but is much more optimized. Highly optimized animations will almost always require a lot more code.
    6 points
  6. Hi @Anael_, welcome to the forum ! πŸ’š There are many ways to solve this and I created one for you πŸ™‚. The problem when using position absolute is that you lose the .container dimension (width, height) and if the elements were not positioned with position absolute animation can get weird. So I created this, only animating the transform x, y, calculating the container dimensions and the left position of the element. https://codepen.io/nicofonseca/pen/XWareXV?editors=0110 I hope this helps πŸ™Œ
    6 points
  7. Hey Creek, If you want to handle logic within functions and pass parameters it may be best to use the methods that were made for that, like onComplete() or call() I'd also advise that you stay away from fancy arrow functions entirely until you have a better understanding of JS. Just stick with normal functions for now. (Some people may disagree with me here) But from experience teaching, there's less chance of getting confused about scope so it avoids unnecessary confusion. You can also create functions this way that are called from your timeline but instantiated elsewhere. This keeps your code nice and easy to read. I've put a playground together for you here. https://codepen.io/GreenSock/pen/VwzZWQm Also a note - I would consider myself experienced with JS and GSAP. I still have to put together minimal demos like the one above in order to test and understand things. When people ask questions here, the people that answer aren't necessarily drawing on knowledge that's immediately available. People helping have to: Read the post Read the code Extrapolate what the question is Read/reference the docs or search the forums for helpful threads Make a demo if one isn't provided Work out a solution Explain the solution It's quite time-consuming and a lot of the people in here do this voluntarily in addition to other work. You can help by keeping your posts as short as possible. Just outline the specific question and provide a minimal demo. Thanks
    6 points
  8. Hi @tibo78, when you use $('.whatever') jQuery will target all those elements from your page, so it is the same as document.querySelectorAll('.whatever'). So when you use those elements to animate with GSAP all are affected. You need to target only the elements you want to animate, you can do something like this: https://codepen.io/nicofonseca/pen/0aa7834959a64963e469a2d64e5328ec
    6 points
  9. Hello @BradLeeCoop - welcome to the forums. That probably is no out-of-the box effect that comes with any library, but something custom made with the help of WebGL - in this case I think they used pixiJS. There are some articles over on codrops explaining how to do similar effects with three.js - maybe these here can help you get started. https://tympanus.net/codrops/2019/10/23/making-gooey-image-hover-effects-with-three-js/ https://tympanus.net/codrops/2020/04/14/interactive-webgl-hover-effects/
    6 points
  10. Enhancement: I added the ability to define values in an Array for a more simplistic way to just go to certain values, split equally across the whole animation, like: keys: { scale: [1, 0.5, 1.5, 1] } To be clear, that first value in the Array isn't a "from" value - it's the first destination. So, for example, if scale is 0 when that tween renders for the first time, it'd go 0 > 1 > 0.5 > 1.5 > 1 over the course of the whole tween. So with this syntax, it gives you the flexibility to use the percent-based values when you need them spaced non-evenly or to use a non-linear ease, -OR- use the shorter Array-based syntax for evenly-spaced linear values. πŸ‘ I'm not set on the "keys" name, so if anyone has a better idea, I'm all ears. New plugin: gsap.registerPlugin({ name: "keys", init(target, vars, tween) { let tl = this.tl = gsap.timeline(), add = (prop, obj) => { let a = [], p; if (Array.isArray(obj)) { obj.forEach((value, i) => a.push({t: (i + 1) / obj.length * 100, v: value})); } else { for (p in obj) { p === "ease" || a.push({t: parseFloat(p), v: obj[p]}); } a.sort((a, b) => a.t - b.t); } a.forEach((kf, i) => { let v = {ease: obj.ease || "none", duration: kf.t - (i ? a[i - 1].t : 0)}; v[prop] = kf.v; tl.to(target, v); }); tl.duration() < 100 && tl.to({}, {duration: 100 - tl.duration()}); }, p this.tween = tween; this.ease = gsap.parseEase(vars.ease || "none"); for (p in vars) { p === "ease" || add(p, vars[p]); } }, render(ratio, {tl, tween, ease}) { tl.progress(ease(tween.progress())); } });
    6 points
  11. Hey @Syed Azam, welcome to the forum! πŸ’š You can do something like this: https://codepen.io/nicofonseca/pen/e81138427318c2826079e5c3f2ac4d41?editors=1010 The trick to achieve the mask effect is move the parent element to a direction and they child element to the opposite at the same time. gsap.to(parentElement, { xPercent: -100, duration:1 }); gsap.to(childElement, { xPercent: 100, duration:1, }); I hope this can help you. πŸ™‚
    6 points
  12. I'm pretty sure Illustrator has its reasons why it puts out things the way it does - like grouping things. It can not know what you are going to use the output for - and for animating often a rather specific setup is needed, that you will have to tweak yourself. I myself am not familiar enough with Illustrator for being able to give you any advice on what you could possibly do better there. As mentioned, it is pretty much that's going on in your demo. If you need assistance, it is always best to strip things down to the bare minimum showcasing what you do have problems with. Not only will it help you figure things out easier, but also does it help others figure out what the problem might be and how to possibly find a solution. And with lots of code, that can become quite cumbersome. Here is your example boiled down to just the left eye - and everything related to that wrapped in a group with the clip-path applied. I did remove all the other clip-paths set to other elements in there - unfortunatelly, I can not clean it all out for you, but a setup like this appears to be working as I would expect it to work. https://codepen.io/akapowl/pen/df10519493a5b3e5785ee9f2343d01c5
    6 points
  13. Hi monospace! .addPause() will only work with a timeline, but you could do something like this using delayedCall. let tl = gsap.timeline() .to(".blob", { y: 200, duration: 9, ease: "none" }) .addPause(3, function(){ gsap.delayedCall(2, () => tl.resume()); }) .addPause(6, function(){ gsap.delayedCall(2, () => tl.resume()) })
    6 points
  14. Hello @jenda In that case you could just set up an extra ScrollTrigger for the pinning of the "19" with an endTrigger set alongside of the end to easily tell where it is supposed to stop pinning, and let the ScrollTriggers within the loop handle the rest. The pen below shows how you you handle the ScrollTriggers in the loop it 'timingwise', dependent on the height of each .content You can certainly do that in the onLeave callback as to be seen in the pen below - but don't forget do fade them back in onEnterBack. Happy scrolling! https://codepen.io/akapowl/pen/c5c949193e94621afc717cbce169bc96
    5 points
  15. Hi there Mantrone! Welcome to the forums and thanks for joining club GSAP How about something like this as a starting point? https://codepen.io/GreenSock/pen/qBXdywG?editors=1010 You can control how the morph looks by tweaking the shapeIndex - read the docs for more info ☺️
    5 points
  16. The issue is the arrow function. The same goes for using let. IE is forever stuck using an older version of JavaScript. Most people use babel to do the conversion, or they don't even worry about IE because it's a waste of time as Microsoft doesn't even support it. var mobile_menu = gsap.timeline({ scrollTrigger: { trigger: "#site_content", toggleActions: "play none none none", start: "top top", end: "bottom bottom", onUpdate: function(self) { if(self.direction == -1){ mobile_menu.reverse(); } else if (self.direction == 1){ mobile_menu.play(); } } } });
    5 points
  17. let explodeCont = document.querySelectorAll('.anim-explode-container'); explodeCont.forEach((container) => { let svg = container.querySelector('.anim-explode'); let shapes = [ 'M254 286.11a50 50 0 0050-50H204a50 50 0 0050 50z', 'M255.5 271a20 20 0 10-20-20 20 20 0 0020 20zm0 30a50 50 0 10-50-50 50 50 0 0050 50z', 'M307.5 250a50 50 0 11-50-50 50 50 0 0150 50', 'M234 237a22.5 22.5 0 0045 0h27.5a50 50 0 01-100 0z', 'M258 202.5a12 12 0 00-12 12v26h-26a12 12 0 000 24h26v26a12 12 0 0024 0v-26h26a12 12 0 000-24h-26v-26a12 12 0 00-12-12z', ]; container.addEventListener('mouseenter', (e) => { let animatedShapes = []; for (var i = 0; i < 10; i++) { let newElement = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' ); newElement.setAttribute('d', gsap.utils.random(shapes)); newElement.style.fill = gsap.utils.random([ '#4899DF', '#f0f0f0', '#00C0CC', '#DE2870', '#C7DBF4', ]); svg.appendChild(newElement); animatedShapes.push(newElement); } function killShapes() { animatedShapes.forEach((shape) => { svg.removeChild(shape); }); } gsap.set(animatedShapes, { transformOrigin: 'center', scale: 'random(0.2, 1)', }); gsap.to(animatedShapes, { onComplete: killShapes, keyframes: [ { rotate: 'random(180, -180)', x: 'random([-150, -100, -200, 200, 100, 150])', y: 'random([-150, -100, -200, 200, 100, 150])', ease: 'expo.out', duration: 4, stagger: { amount: 0.1, }, }, { opacity: 0, delay: -3 }, ], }); }); }); Apologies for the wall of code - but I did a similar thing on this site for the tickets button up at the top right. Might be helpful to see another approach. It's using SVG which is quite nice for responsive/crisp vector stuff (I'll try to loop back and pop this in a codepen next week, but I have sunday roast and wine waiting right now πŸ‘€)
    5 points
  18. Hey there @Dipit Maurya I'd probably work with a data-attribute on each .inner-listing for something like that. Maybe something like this: https://codepen.io/akapowl/pen/c95cfa7260c37ea092daef8f5c92fd13 Edit: ... here is another version, polished up a bit with regard to margins/padding and a slight change on the start/end of the ScrollTrigger. https://codepen.io/akapowl/pen/d4b4927ba6227d308fb947c1cf4f388d
    5 points
  19. Here you go @Catalin R. What is important, is to make sure that you still specifically set the body as the scroller and the pinType to "transform" - I did it here via ScrollTrigger.defaults(). Just as a little sidenote: You are actually applying a third-party smooth-scrolling library to work on the body - and then hooking up ScrollTrigger to that smooth-scroll via the .scrollerProxy(). https://codepen.io/akapowl/pen/16d802e8f90b1795ca1b86e2da67232a
    5 points
  20. Hi @rala , welcome to the forum! πŸ’š GSAP has been in the market for a long time and has lots of tutorials (free and paid) and also you can find more stuff inside the forums. If you want to start some courses I can recommend these ones: https://www.creativecodingclub.com/ https://www.motiontricks.com/ And to learn more about the effects you were looking you can go to the forum, for example: Hope this helps and if you have any issue you can ask on the forum providing a minimal demo and we'll help you! πŸ™Œ
    5 points
  21. Try this: onLeave: function(self) { self.scroll(self.start); // <-- sets position to start of ScrollTrigger self.disable() self.animation.progress(1) } https://codepen.io/akapowl/pen/2f164f6fc6ea04ad8480421d9b3cd011
    5 points
  22. New version of CreateJS came out then, so you need to specify the updated CDN link in your head. OLD to replace: <script src="https://code.createjs.com/createjs-2015.11.26.min.js"></script> NEW: <script src="https://code.createjs.com/1.0.0/createjs.min.js"></script> Or via Google's CDN > <script src="https://s0.2mdn.net/ads/studio/cached_libs/createjs_2019.11.15_min.js"></script> Once updated, should work fine.
    5 points
  23. Welcome to forums @rsheppard Animating a CSSRule will apply to all pseudo elements that use that rule. You should use CSS variables instead. Also, never use CSS transitions on properties that you are animating with GSAP. Using all, applies to all properties, so it will mess up your GSAP animations. GSAP Underline Animation (codepen.io)
    5 points
  24. Here are some notes on that; You are initially creating a tween (scrollTween) on all sections and then again in the forEach loop also create a tween for each individual section. You shouldn't do that - in the fake-pinning example the only tweens created are in the forEach loop When checking if an element has a class, don't include the leading '.' // bad thumb.classList.contains('.fakePin') // good thumb.classList.contains('fakePin') You forgot to change the container variable in the individual tweens to mainContainer - a container variable doesn't exist in your example. There are no margins on your panels, but instead you are making use of the grid-column-gap, so instead of the marginRight of the element that is being considered in the getTotalWidthToMove() function, you will have to get the gridColumnGap of the parent. I also made some changes to the CSS in this following example, so you might need to consider addapting that for things to work properly https://codepen.io/akapowl/pen/db4c5133bf37a7f617fceda56f94c8dc
    5 points
  25. Heya Hannah! You can use invalidate() in this sort of situation. .invalidate( ) : self [override] Flushes any internally-recorded starting/ending values which can be useful if you want to restart an animation without reverting to any previously recorded starting values. https://codepen.io/GreenSock/pen/abwMweQ?editors=0011
    5 points
  26. Hello there @qvstudio. You can set an endalongside an endTrigger. With the endTrigger you can target the section you want the end to trigger on and with the end you can define at which point in the viewport for that section the ScrollTrigger is supposed to end. https://codepen.io/akapowl/pen/b21e2d07d0ec48b8490d86945e66f4b0 From the ScrollTrigger docs: endTrigger String | Element - The element (or selector text for the element) whose position in the normal document flow is used for calculating where the ScrollTrigger ends. You don't need to define an endTrigger unless it's DIFFERENT than the trigger element because that's the default.
    5 points
  27. For the lines that are supposed to be moving to the right, you will likely have to make sure that they start with their right side against the right side of the window (which is basically where you are tweening the other one to); so I would probably make use of a fromTo tween for that, with which you can declare their starting position in the from part - something like I did in this horizontal-scrolling example. https://codepen.io/akapowl/pen/dyvygmj That pen creates a ScrollTrigger forEach of the 'sections' - which can give you a bit more control. Here's what that could look like with your example https://codepen.io/akapowl/pen/a5e95c5b1cafbdc1d8d12d58a030407e
    5 points
  28. Sounds like you're using it correctly. It's just a visual aide to help people understand how shapeIndex works, no drag and drop or complexity to it. You can use CSS to position your SVG differently if you need to? https://codepen.io/GreenSock/pen/qBjQmKJ Yes, you can omit it. shapeIndex is just an option - if auto works you don't have to specify anything. It will default to auto. Sounds like learning to code! It takes a long time to build up all the little bits of satellite knowledge and then the strings to connect them. It shouldn't be a 'major bummer' though. Especially seeing as you're learning to animate a fish... Compared to a lot of things you have to learn in this industry animating fish is definitely on the fun side of things! Don't be so hard on yourself, everyone starts off not understanding anything. We've all been here. Just take it slowly.
    5 points
  29. I removed them because you had them a) in multiple places and b) on elements that you are translating with tweens on. As already mentioned by @GreenSock, that will throw things off. Instead, as suggested, I added the clip-path attribute on the group I created around everything related to the left eye - maybe that's the part you missed. This setup now only contains things related to the left-eye, so you will also want to create a similar setup for the other eye and maybe even clean it out a bit, too. <g clip-path="url(#N_EyeMask_L_clip)"> // <----- <g id="Face_Perturbed_11"> ... </g> <g id="P_Eye_L"> ... </g> <g id="Face_Normal_16"> ... </g> <g id="N_Eye_L"> ... </g> </g> No worries, I know how hard it can be. Just starting out with things can be overwhelming enough, trying to understand how everything works. Having a wall of code facing you will not be very helpful in that case - that's why it would be best to start small with just a handful of elements - something like in my initial examples - and work your way up from there, adding piece by piece and seeing what it changes.
    5 points
  30. That example is using ScrollTrigger with GSAP, it's a pretty straight forward effect. You are pinning the current block you are on, and scrolling content over the top of that. Check the main docs here: https://greensock.com/docs/v3/Plugins/ScrollTrigger This is a good resource: https://www.creativecodingclub.com/courses/scrolltrigger-express?ref=44f484 This covers the main idea: https://codepen.io/GreenSock/pen/KKpLdWW
    5 points
  31. Every tween you have is calling doBackground. You need to add it conditionally like this. let vars = {duration:0.55, yPercent:100, stagger:0.03,ease:'power4.out'}; if (index === 1) { vars.onComplete = doBackground; } tl.from(chars.chars, vars, ">-30%") Or you could just put the callback in your timeline. if (index === 1) { tl.add(doBackground) }
    5 points
  32. Hi Dipit, If you don't want the white-space (which is the spacing added by the pin-spacer) showing when pinning things like that, you'd want to consider wrapping all your content in a div and pinning this wrapping div instead. https://codepen.io/akapowl/pen/954ea945a4ec2db0f6aa8c35168c6f15 For any subsequent ScrollTriggers on elements within that wrapping div, you will then need to set the pinnedContainer property to that pinned wrap, as they won't have any pinSpacing to consider for their positioning (because they are inside the pinSpacer of the pin you created before) and thus will not get the correct values as you might expect, otherwise. Hope that helps
    5 points
  33. You are repeating a bunch of stuff in your mouse handler. More like this. Correct quick setter (codepen.io)
    5 points
  34. @obaidnadeem This is definitely using some sort of WebGL for the rendering. GSAP works great for animating WebGL objects (Lots of example on the forms here). Interestingly enough, there's a Twitch Stream today covering using GSAP with WebGL shaders:
    4 points
  35. It looks like GSAP is setting the overflow when you resize, so you can just change it again onRefresh... A Pen by GreenSock (codepen.io)
    4 points
  36. Just Added Width Expansion to my codepen above, feel free to adjust the Easing and Duration to match your Needs (Tranform X Y -50% doesn't seem to be working in this miniviewer, open codepen in another tab for correct display) https://codepen.io/blitzve0/pen/vYJGPaa
    4 points
  37. Hey there sarathchand19, Welcome to the forums. πŸ₯³ This sounds like a z-index issue. I'd recommend making sure the s-i element is actually able to be hovered and not being blocked by other elements on top of it. This won't be down to GSAP itself, but a side effect of whatever styling you've applied. It's not possible to help any further without seeing a codepen or codesandbox demo though I'm afraid. I hope this helps point you in the right direction
    4 points
  38. Hello @AnimatiCSS Unfortunately, ScrollTrigger's pinning will not work with sections that have locomotive-scroll's data-scroll-section attribute, as when using that data-attribute, locomotive-scroll will work its translates for the smooth-scrolling on those sections and thus will inevitably tell those sections to keep on moving/translating, so there will be conflicting behaviour between locomotive-scroll and ScrollTrigger, that ScrollTrigger can not do much about.
    4 points
  39. Hey there welcome to the forums! This is an easy thing to get confused by. You're looking for a loop. https://codepen.io/GreenSock/pen/eYENLLw This article is a good read if you want to avoid common mistakes
    4 points
  40. Welcome to the forums @dve46 I would put a wrapper element around the canvas and use that instead since the inline styling that GSAP is apply for the pinning is not going to match the attributes that three.js sets. ScrollTrigger Pinning with three.js (codepen.io)
    4 points
  41. Anonymous functions aren't hoisted.
    4 points
  42. Welcome to the forums @Vijay Seetaram Raju All your panels are block elements, which makes them appear stacked vertically. If you want some horizontal fake-scrolling, you will first have to style things properly - e.g. use flex on a container surrounding all those sections you want to scroll horizontally, as in this follwoing pen. https://codepen.io/akapowl/pen/58790bb6cbb8f64ebfef48b36bbee36c
    4 points
  43. Hi @blizve0 Here's a fork of your demo with some custom hooks, which should optimize it tad bit more. Cursor Jelly Blob (codepen.io)
    4 points
  44. Hi CreativeRobot, Sure, happy to give some pointers. Your first and last tween are doing the same thing, so you don't need both. You also don't need yoyo in the first one - yoyo alternates the direction of repeating tweens, and that tween isn't repeating You can add defaults to a timeline if your tweens are using the same values repeatedly. You could write this in just one tween. gsap.to(".logo", { opacity: 0, xPercent: -100, duration: 1, repeat: 1, yoyo: true, repeatDelay: 5, ease: "power1.out", }) But the ease would be reversed. Here's another option with separate tweens and the easing you had applied originally. https://codepen.io/GreenSock/pen/yLXwJea?editors=1010
    4 points
  45. Hi Aki-sol, That looks to me like a standard image scale. You can just say scale:1.4 That will use a transform. There's a list of properties you can use in this article -
    4 points
  46. Hey @NickWoodward. This seems like a browser render issue. You can try adding a higher z-index in the pseudo element or adding a translate3d(0,0,0) / translate3d (0,0,1px) πŸ™‚
    4 points
  47. You'll have to create some logic that looks at current x and y positions and limits the next next move if the += goes over that. Something like: if (currentXPosition + xMov > xBoundry) { xMov = `+=${xBoundry - currentXPosition}` } else { xMove = `+=${moveUnit}` } or better yet, you could use the gsap clamp utility to keep your position within certain bounds: https://greensock.com/docs/v3/GSAP/UtilityMethods/clamp() gsap.to(el, { x: gsap.utils.clamp(0, 900, currentPosition + moveUnit) })
    4 points
  48. Since each of your .circle_icon divs are children of the parent circle they will rotate along with the parent. By using a tween targeting only the icon rotation in the opposite direction, you give the appearance of the icons/text remaining upright. It just needs to be the opposite of the parent. If the parent circle is rotating 720 then you'd need to rotate the icons -720 over the same duration. Make sense?
    4 points
  49. Hi leonardphb! For that you would use the MotionPathPlugin. https://greensock.com/docs/v3/Plugins/MotionPathPlugin Everything will work basically the same, except there is not a "soft" type anymore... Tween timeScale() (codepen.io) That helper function comes from this thread.
    4 points
  50. @OSUblake @Cassie I just found out that my problem was caused by page transitions. When I throw them away, everything works as it should with GSAP ScrollTrigger Here is the code that caused the problem: _layout.selte <script> import Header from '$lib/global/Header.svelte'; import Footer from '$lib/global/Footer.svelte'; import '../styles/c.css' import PageTransitions from '$lib/global/PageTransitions.svelte'; import { navigating } from '$app/stores'; </script> <Header/> <main> <PageTransitions refresh={$navigating}> <slot/> </PageTransitions> </main> <Footer/> PageTransitions.svelte: <script> import { fly } from 'svelte/transition'; export let refresh = ''; </script> {#key refresh} <div in:fly="{{ y: 10, duration: 300, delay: 300}}" out:fly="{{ y: 10, duration: 300 }}"> <slot/> </div> {/key} Now I need to figure out how to use page transitions to get them working with SrollTrigger, but at least half of my problem has been solvd and I'm already happy. πŸ‘
    4 points
Γ—