Leaderboard
Popular Content
Showing content with the highest reputation on 02/08/2023 in all areas
-
Hello Pauline. That is because you set it up to be triggered, when each quote's top hits the vertical center of the viewport - since all of them are positioned in a way, that they already are past that point (vertically), the tweens will trigger on load. For triggering tweens on individual parts of a fake-horizontal scrolling tween, you'll want to have a look at containerAnimation https://greensock.com/docs/v3/Plugins/ScrollTrigger containerAnimation Tween | Timeline - A popular effect is to create horizontally-moving sections that are tied to vertical scrolling but since that horizontal movement isn't a native scroll, a regular ScrollTrigger can't know when, for example, an element comes into view horizontally, so you must tell ScrollTrigger to monitor the container's [horizontal] animation to know when to trigger, like containerAnimation: yourTween. See a demo here and more information here. Caveats: the container's animation must use a linear ease ( ease: "none"). Also, pinning and snapping aren't available on containerAnimation-based ScrollTriggers. You should avoid animating the trigger element horizontally or if you do, just offset the start/end values according to how far you're animating the trigger. If you want the tween to snap to a certain point, once a user has stopped scrolling, you'll want to have a look at snap. https://greensock.com/docs/v3/Plugins/ScrollTrigger snap Number | Array | Function | Object | "labels" | "labelsDirectional" - Allows you to snap to certain progress values (between 0 and 1) after the user stops scrolling. So snap: 0.1 would snap in increments of 0.1 (10%, 20%, 30%, etc.). snap: [0, 0.1, 0.5, 0.8, 1] would only let it come to rest on one of those specific progress values. It can be any of the following: [...] I only just hardcoded the values that would work in your demo in an array just to give you an idea with the example below. But you could also calculate the values inside a function - although, of course that would be a bit more advanced and you'd have to figure out the logic for that to work with your scenario. I hope that this will help. https://codepen.io/akapowl/pen/VwBOWEZ4 points
-
Hi @Kenken94 welcome to the forum! Don't worry about asking 'basic things' here. Looping animation can be really tricky, but luckily our @Carl dit an in depth tutorial about it which is a great watch and easy to follow. I do have to saw that this is a bit advanced topic if it is your first animation, but I think if you pay close attention and watch the demo he provided. For the rest of your setup I would work with opacity: 0; instead of display: none; I'm not completely sure, but something tells me that images do not load if they are display: none; so when you set them to display: block; with GSAP the images first need to load which could result in weird effects. Also just something to keep in mind .fromTo() tweens are great, but personally I rarely use them, if your element is al ready at it end state (or begin state) a simple .from() or .to() is all you need. You could also look into clipPath, it's a different effect, but it is more performant then animating the width of something (I've used the following tool to create the clip-path's https://bennettfeely.com/clippy/. Sorry, maybe a bit of information overload, but I would suggest trying your hand at a new demo with this information and post back here if you have a new demo with a question. Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/eYjagaL?editors=00104 points
-
Hi @Okaia and welcome to the GreenSock forums! First thanks for being a Club GreenSock member and supporting GreenSock! This example of the container animation implements the Observer Plugin in order to update the animation with the regular mouse wheel and swipe left/right on that particular section (line 30 of the JS tab): https://codepen.io/GreenSock/pen/NWMxRvM Hopefully this is enough to get you started. Let us know if you have more questions. Happy Tweening!3 points
-
I'd dispute this (but also open to be corrected, SVG can be a little wonky sometimes) I don't know of any browser inconsistencies for using JS in SVG. You can't use modules but JS is fine. You have to be aware that you're in SVG-land so certain HTML specific web API's or methods like .getBoundingClientRect won't work, maybe that's what tripped you up @iDad5? But you have SVG methods like .getBBox so it's not the end of the world. ✨ lil' demo for testing https://codepen.io/GreenSock/pen/dyjEvJp?editors=11003 points
-
hi drNo77, Just put it in a loop and you won't have to repeat copy and paste the same tween again https://codepen.io/tcb2307/pen/PoBvGbj3 points
-
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 https://codepen.io/snorkltv/pen/ZEjNvKw?editors=1010 Hope this helps2 points
-
Hi, Maybe you should take a look at ScrollTrigger's batch method: https://greensock.com/docs/v3/Plugins/ScrollTrigger/static.batch() Here is a live example: https://codepen.io/GreenSock/pen/NWGPxGZ In the case of your last codepen example it would be as simple as this: gsap.registerPlugin(ScrollTrigger); gsap.set(".grid-i", {y: 50, opacity: 0}); ScrollTrigger.batch(".grid-i", { onEnter: batch => gsap.to(batch, {opacity: 1, y: 0, stagger: 0.15, overwrite: true}), }); Hopefully this helps. Let us know if you have more questions. Happy Tweening!2 points
-
What I would do is create a timeline of your progress bar (you'd done that already). Instead of animating the width of something I gravitate to other properties, because width isn't that performant, in this case animating the scale would do the exact same thing and is better for performance. So right now we have a timeline that animates the line from 0 scale to 1 scale. If we then pause that timeline, so it does nothing on page load, we could tween that timeline to a specific progress point on that timeline (A timeline has a progress from 0 to 1, where 0 equals to nothing has played and 1 the animation has fully played). If we then feed in your number to that progress we could tie the two together. Using the number directly wounding work, because your scale is from 0 to 100 and the progress needs a value between 0 and 1, but just dividing the number by 100 fixes this. Hope it helps and happy tweening! https://codepen.io/mvaneijgen/pen/VwBOrKg?editors=00102 points
-
Hi Rodrigo, thanks a lot for your quick help. I'll test it to see if it has the desired effect. By the way, the greensock forum is really great! 😀 Thanks2 points
-
Hello Laurence. The way your demo is set up, the onToggle callback of your fake-horizontal ScrollTrigger, will (except for when the STs are being created) never be called, because that ScrollTrigger will always be active - you can check that by adding some console.log() to that callback. [Some slight correction: It will trigger at the end in this scenario - you just did not add the onToggle callback to the scrollTrigger object, but outside of it instead.] But if you want to trigger something for individual sections inside that container, using that callback wouldn't be the way to go to begin with, as it would only trigger when that ScrollTrigger toggled between active/inactive - not the individual parts inside of it. If you want to trigger something on individual parts of your fake-horizontal tweening container/sections, you should have a look at containerAnimation. https://greensock.com/docs/v3/Plugins/ScrollTrigger containerAnimation Tween | Timeline - A popular effect is to create horizontally-moving sections that are tied to vertical scrolling but since that horizontal movement isn't a native scroll, a regular ScrollTrigger can't know when, for example, an element comes into view horizontally, so you must tell ScrollTrigger to monitor the container's [horizontal] animation to know when to trigger, like containerAnimation: yourTween. See a demo here and more information here. Caveats: the container's animation must use a linear ease ( ease: "none"). Also, pinning and snapping aren't available on containerAnimation-based ScrollTriggers. You should avoid animating the trigger element horizontally or if you do, just offset the start/end values according to how far you're animating the trigger.2 points
-
No need for the whole back story, this should do it... Have you tried this with transforms (transform: translateX(100%); etc.) instead of positive and negative left values (browsers don't like repainting position values, and this can cause some visual bugs sometimes, but they do handle transforms nicely)? Also, do you have a width and max-width set on the overflow: hidden; container? One other thing you could try is the old trick of adding backface-visibility: hidden, or the newer, and more reliable, trick of will-change (https://developer.mozilla.org/en-US/docs/Web/CSS/will-change). I usually use will-change: transform;, but will-change: scroll-position; sounds interesting in this instance. Did I win the Whisky? Honestly, mostly just shooting in the dark over here, but if I had a working link or demo that showed the bug, I'm fairly sure I could help solve your issue.2 points
-
@Carl is correct, you cannot target individual pieces of a pattern. Also, if you are animating pieces of SVG patterns, the performance is really really bad (from personal experience).2 points
-
Hi, A few things. First in the function you're using to show the element you should call ScrollTrigger.refresh() so ScrollTrigger calculates the start and end points again. Also I wouldn't recommend display none since it's really messing up the position of the elements after SplitText does it work. I think this is a better approach: https://codepen.io/GreenSock/pen/xxJNQmm Hopefully this helps. Let us know if you have more questions. Happy Tweening!1 point
-
If I were you, I'd make a copy of your project and remove EVERYTHING you possibly can and still have it broken. Then I'd literally open that [problematic] page in the browser and save the source. Post that so others can open it, crack open Dev Tools and see what's going on. Don't make people have to run your whole build process - just shortcut to the problematic HTML/CSS/JS that can be opened in the browser. Just an idea. Good luck!1 point
-
Hey Rodrigo, Just another update. I'm pretty certain now that I have to use the offset Y to create the calculation for it to land properly on the section! Thank you!1 point
-
Yep, @akapowl is right, you need to set your fixed elements outside the smoother container: <div id="smooth-wrapper"> <div id="smooth-content"> <!--- ALL YOUR CONTENT HERE ---> </div> </div> <!-- position: fixed elements can go outside ---> Here is a fork of that codepen example using ScrollSmoother so you can see it in action: https://codepen.io/GreenSock/pen/oNMRdBX Hopefully this clear things up. Let us know if you have more questions. Happy Tweening!1 point
-
Ok, I try and share a demo, thanks!!! It seems easier than I thought1 point
-
Sounds great! I'd be shocked if the paint "bug" was due to any sort of dependencies.1 point
-
Hi, Just create a couple of GSAP set() instances in order to go to the top/bottom of the document: https://greensock.com/docs/v3/GSAP/Tween/set() Something like this: const topBtn = document.getElementById("top"); topBtn.addEventListener("click", () => { gsap.set(window, { scrollTo: 0 }); }); const bottomBtn = document.getElementById("bottom"); bottomBtn.addEventListener("click", () => { gsap.set(window, { scrollTo: "max" }); }); I updated the codepen example to include both buttons: https://codepen.io/GreenSock/pen/zYLMdwP Also I'm using fastScrollEnd in order to set the animations to their end state. You can read more about it here (and watch @Carl's video, it's a great explanation of how it works): https://greensock.com/3-8#preventOverlapsAndFastScrollEnd Let us know if you have more questions. Happy Tweening!1 point
-
1 point
-
Hi, Using the original example Jack created it should be as simple as this: https://codepen.io/GreenSock/pen/BaPeYdM Hopefully this helps. If you keep having issues please remember to include a minimal demo of what you have. Happy Tweening!1 point
-
Fair enough on the whisky, but now I'm wondering what could be causing your bug... Ping this thread when you have a something working to show the issue... Browsers usually don't go off the rails (the exception being Safari) these days, so I'm sure it's something simple that's being overlooked, or could use a fresh set of eyes... Can this be reproduced with divs and a quick class toggle in CodePen?1 point
-
1 point
-
Here's an explanation for why that happens, and suggestions for how to work around that, from the documentation, @Tomas100 https://greensock.com/docs/v3/Plugins/ScrollSmoother Caveats position: fixed should be outside the wrapper - since the content has a CSS transform applied, browsers create a new containing block and that means position: fixed elements will be fixed to the content rather than the viewport. That's not a bug - it's just how CSS/browsers work. You can use ScrollTrigger pinning instead or you could put any position: fixed elements OUTSIDE the wrapper/content.1 point
-
That's totally fine. There are no such restrictions. Also, I think you can embed JavaScript directly in SVG files. A quick Google search returned: http://thenewcode.com/1094/Using-JavaScript-in-SVG I believe I did that myself years ago. Just had to do the //<![CDATA[ wrapper like the article says. You could copy the GSAP file contents into a script tag and then directly under the GSAP code, write your custom code. I assume that'd work. But it's probably a lot easier to do the <script xlink:href="external.js" /> thing if you can get away with it (again, see the article). Good luck!1 point
-
Hi @FaxForceFive. Your question wasn't very clear to me. Help? Vague details like 'I'm having problems with the timings' are very difficult for people to help with. Here are some tips that will increase your chance of getting a solid answer: A clear description of the expected result - "I am expecting the purple div to spin 360degrees" A clear description of the issue - "the purple div only spins 90deg" A list of steps for someone else to recreate the issue - "Open the demo in any browser and scroll down to the grey container" A minimal demo ✅ We'd love to help with any GSAP-related questions...we just need some assistance understanding what you're asking specifically.1 point
-
You added margin-bottom, that's why they're spaced out more. It has nothing to do with ScrollTrigger. You can eliminate ScrollTrigger completely and your spacing remains the same. Sorry, I'm still completely lost. I watched your video and I see the footprints happening on scroll. I have no idea what you think is broken or what you want to work differently. The demos I provided show the footprints happening on scroll - what's wrong? I think I've provided a lot of options for you already, so hopefully you can tweak the values to get whatever effect you want. Good luck.1 point
-
Hi @codevelop_at and welcome to the GreenSock forums! Indeed that can be created with GSAP using a quickTo instance: https://greensock.com/docs/v3/GSAP/gsap.quickTo() However you'll have to track the mouse position relative to the list item, since the image container is on top of the list and that would prevent from the items to receive any mouse event. So you have to check the mouse position in the parent container of the list and then, based on the Y position of the mouse update the image. Unfortunately this is not a super simple task and is a little beyond the help we can provide in these free forums. Of course if another user can chime in and help or offer some working example or approach, great! Good luck with your project and if you have any GSAP related question, let us know. Happy Tweening!1 point
-
Hi, There are a couple of issues with your example. First you're not including and registering the ScrollTo Plugin, so that's not going to work. Once you include the plugin you're not preventing the default behaviour on the click event so it goes directly to the anchor, which completely removes any animation and most likely is moving the menu. Finally you have this in your code: gsap.to("#section" + (index + 1), { duration: 1, scrollTo: { y: "#section" + (index + 1) } }); Basically you're telling GSAP to scroll the element with the specific ID, you have to scroll the window object since that is the scroller element in your setup. This seems to work as you expect (albeit with some calculation errors it looks like, but you should be able to figure those out): document.querySelectorAll(".scrollNav a").forEach((btn, index) => { btn.addEventListener("click", (e) => { e.preventDefault(); gsap.to(window, { duration: 1, scrollTo: { y: "#section" + (index + 1), autoKill: true, } }); }); }); Hopefully this helps. Let us know if you have more questions. Happy Tweening!1 point
-
Just circling back to this - the latest beta seems to work well. You just have to call ScrollTrigger.update() after lenis does its update (basically, tell ScrollTrigger "hey, my scrolling position changed using a 3rd party library!") https://codepen.io/GreenSock/pen/RwBbvvw?editors=10101 point
-
This was a fun chance for me to whip up a helper function that lets you dynamically figure out the rows/columns as well as further refine those with "odd" or "even" ones: function getGrid(selector) { let elements = gsap.utils.toArray(selector), bounds, getSubset = (axis, dimension, alternating, merge) => { let a = [], subsets = {}, onlyEven = alternating === "even", p; bounds.forEach((b, i) => { let position = Math.round(b[axis] + b[dimension] / 2), subset = subsets[position]; subset || (subsets[position] = subset = []); subset.push(elements[i]); }); for (p in subsets) { a.push(subsets[p]); } if (onlyEven || alternating === "odd") { a = a.filter((el, i) => !(i % 2) === onlyEven); } if (merge) { let a2 = []; a.forEach(subset => a2.push(...subset)); return a2; } return a; }; elements.refresh = () => bounds = elements.map(el => el.getBoundingClientRect()); elements.columns = (alternating, merge) => getSubset("left", "width", alternating, merge); elements.rows = (alternating, merge) => getSubset("top", "height", alternating, merge); elements.refresh(); return elements; } Usage: let grid = getGrid(".grid-i"), // first get the grid which is actually an Array of all the elements rows = grid.rows(), // all rows evenRows = grid.rows("even"), // just the even ones oddColumns = grid.columns("odd"); // just the odd columns It returns an Array with an Array for each column/row. You can even pass in true as the 2nd parameter to have it merge them all into a flat Array. Demo: https://codepen.io/GreenSock/pen/KKexgWp?editors=0010 I hope that's useful.1 point
-
Are you guilty of any of the most common mistakes people make in their ScrollTrigger code? Nesting ScrollTriggers inside multiple timeline tweens Creating to() logic issues Using one ScrollTrigger or animation for multiple "sections" Forgetting to use function-based start/end values for things that are dependent on viewport sizing Start animation mid-viewport, but reset it offscreen Creating ScrollTriggers out of order Loading new content but not refreshing Why does my "scrub" animation jump on initial load? Or my non-scrub animation start playing? Tip: How to make scrub animations take longer Navigating back to a page causes ScrollTrigger to break Note: There's also a separate article that covers the most common GSAP mistakes. Debugging tip: In many cases, the issue isn't directly related to ScrollTrigger, so it's helpful to get things working without ScrollTrigger/any scroll effects and then, once everything else is working, hook things up to ScrollTrigger. Nesting ScrollTriggers inside multiple timeline tweens A very common mistake is applying ScrollTrigger to multiple tweens that are nested inside a timeline. Logic-wise, that can't work. When you nest an animation in a timeline, that means the playhead of the parent timeline is what controls the playhead of the child animations (they all must be synchronized otherwise it wouldn't make any sense). When you add a ScrollTrigger with scrub, you're basically saying "I want the playhead of this animation to be controlled by the scrollbar position"...you can't have both. For example, what if the parent timeline is playing forward but the user also is scrolling backwards? See the problem? It can't go forward and backward at the same time, and you wouldn't want the playhead to get out of sync with the parent timeline's. Or what if the parent timeline is paused but the user is scrolling? So definitely avoid putting ScrollTriggers on nested animations. Instead, either keep those tweens independent (don't nest them in a timeline) -OR- just apply a single ScrollTrigger to the parent timeline itself to hook the entire animation as a whole to the scroll position. Creating to() logic issues If you want to animate the same properties of the same element in multiple ScrollTriggers, it’s common to create logic issues like this: gsap.to('h1', { x: 100, scrollTrigger: { trigger: 'h1', start: 'top bottom', end: 'center center', scrub: true } }); gsap.to('h1', { x: 200, scrollTrigger: { trigger: 'h1', start: 'center center', end: 'bottom top', scrub: true } }); Did you catch the mistake? You might think that it will animate the x value to 100 and then directly to 200 when the second ScrollTrigger starts. However if you scroll through the page you’ll see that it animates to 100 then jumps back to 0 (the starting x value) then animates to 200. This is because the starting values of ScrollTriggers are cached when the ScrollTrigger is created. See the Pen ScrollTrigger to() logic issue by GreenSock (@GreenSock) on CodePen. To work around this either use set immediateRender: false (like this demo shows) or use .fromTo()s for the later tweens (like this demo shows) or set a ScrollTrigger on a timeline and put the tweens in that timelines instead (like this demo shows). Using one ScrollTrigger or animation for multiple "sections" If you want to apply the same effect to multiple sections/elements so that they animate when they come into view, for example, it's common for people to try to use a single tween which targets all the elements but that ends up animating them all at once. For example: See the Pen ScrollTrigger generic target issue by GreenSock (@GreenSock) on CodePen. Since each of the elements would get triggered at a different scroll position, and of course their animations would be distinct, just do a simple loop instead, like this: See the Pen ScrollTrigger generic target issue - fixed with scoping by GreenSock (@GreenSock) on CodePen. Forgetting to use function-based start/end values for things that are dependent on viewport sizing For example, let's say you've got a start or end value that references the height of an element which may change if/when the viewport resizes. ScrollTrigger will refresh() automatically when the viewport resizes, but if you hard-coded your value when the ScrollTrigger was created that won't get updated...unless you use a function-based value. end: `+=${elem.offsetHeight}` // won't be updated on refresh end: () => `+=${elem.offsetHeight}` // will be updated Additionally, if you want the animation values to update, make sure the ones you want to update are function-based values and set invalidateOnRefresh: true in the ScrollTrigger. Start animation mid-viewport, but reset it offscreen For example try scrolling down then back up in this demo: See the Pen ScrollTrigger reset issue by GreenSock (@GreenSock) on CodePen. Notice that we want the animation to start mid-screen, but when scrolling backwards we want it to reset at a completely different place (when the element goes offscreen). The solution is to use two ScrollTriggers - one for the playing and one for the resetting once the element is off screen. See the Pen ScrollTrigger reset issue - fixed with two ScrollTriggers by GreenSock (@GreenSock) on CodePen. Creating ScrollTriggers out of order If you have any ScrollTriggers that pin elements (with the default pinSpacing: true) then the order in which the ScrollTriggers are created is important. This is because any ScrollTriggers after the ScrollTrigger with pinning need to compensate for the extra distance that the pinning adds. You can see an example of how this sort of thing might happen in the pen below. Notice that the third box's animation runs before it's actually in the viewport. See the Pen ScrollTrigger creation order issue by GreenSock (@GreenSock) on CodePen. To fix this you can either create the ScrollTriggers in the order in which they are reached when scrolling or use ScrollTrigger's refreshPriority property to tell certain ScrollTriggers to calculate their positions sooner (the higher the refreshPriority the sooner the positions will be calculated). The demo below creates the ScrollTriggers in their proper order. See the Pen ScrollTrigger creation order issue - fixed by GreenSock (@GreenSock) on CodePen. Loading new content but not refreshing All ScrollTriggers get setup as soon as it's reasonably safe to do so, usually once all content is loaded. However if you're loading images that don't have a width or height attribute correctly set or you are loading content dynamically (via AJAX/fetch/etc.) and that content affects the layout of the page you usually need to refresh ScrollTrigger so it updates the positions of the ScrollTriggers. You can do that easily by calling ScrollTrigger.refresh() in the callback for your method that is loading the image or new content. Why does my "scrub" animation jump on initial load? Or my non-scrub animation start playing? Most likely the ScrollTrigger’s start value is before the starting scroll position. This usually happens when the start is something like "top bottom" (the default start value) and the element is at the very top of the page. If you don’t want this to happen simply adjust the start value to one that’s after a scroll position of 0. Tip: How to make "scrub" animations take longer The duration of a "scrub" animation will always be forced to fit exactly between the start and end of the ScrollTrigger position, so increasing the duration value won't do anything if the start and end of the ScrollTrigger stay the same. To make the animation longer, just push the end value down further. For example, instead of end: "+=300", make it "+=600" and the animation will take twice as long. If you want to add blank space between parts of a scrubbed animation, just use empty tweens as the docs cover. Navigating back to a page causes ScrollTrigger to break If you have a single-page application (SPA; i.e. a framework such as React or Vue, a page-transition library like Highway.js, Swup, or Barba.js, or something similar) and you use ScrollTrigger you might run into some issues when you navigate back to a page that you've visited already. Usually this is because SPAs don't automatically destroy and re-create your ScrollTriggers so you need to do that yourself when navigating between pages or components. To do that, you should kill off any relevant ScrollTriggers in whatever tool you're using's unmount or equivalent callback. Then make sure to re-create any necessary ScrollTriggers in the new component/page's mount or equivalent callback. In some cases when the targets and such still exist but the measurements are incorrect you might just need to call ScrollTrigger.refresh(). If you need help in your particular situation, please make a minimal demo and then create a new thread in our forums along with the demo and an explanation of what's going wrong. Still need some help? The GreenSock forums are the best place to get your questions answered. We love helping people develop their animation superpowers.1 point
-
Welcome the forums @chanced That means whatever tool/framework you are using doesn't support ES Modules, so you would need to import the UMD files. This is a common issue for frameworks that do SSR because of past limited support for ES Modules in a node environment. import Flip from "gsap/dist/Flip";1 point
-
Hey @GreenSock @ZachSaucier, thank you for your answer! The problem was exactly what Jack explained, the height of the body was missing and, as a consequence, nothing scrolled. I've added in the calculations of the scroll that setting and now it works perfectly. 🤟1 point
-
I would highly recommend not doing that for any framework (Vue, React, Angular, etc). querySelector/querySelectorAll can be very problematic with components. Using $refs is the correct approach for selecting elements in Vue. No, that's a Vue file, and it is not an actual script tag. That's all the support I can offer as I'm on mobile right now.1 point
-
Hi friendlygiraffe you can simply use Elastic ease type : http://codepen.io/MAW/pen/KVZwZx/1 point