Jump to content

Search the Community

Showing results for 'overwrite'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


  • GreenSock Forums
    • GSAP
    • Banner Animation
    • Jobs & Freelance
  • Flash / ActionScript Archive
    • GSAP (Flash)
    • Loading (Flash)
    • TransformManager (Flash)

Product Groups

  • Club GreenSock
  • TransformManager
  • Supercharge


There are no results to display.

Find results in...

Find results that contain...

Date Created

  • Start


Last Updated

  • Start


Filter by number of...


  • Start



Personal Website



Company Website



  1. See if this gets you going in the right direction. I just used standalone ScrollTrigger to toggle the nav items. The back ease looks a little bit weird in reverse, so if you wanted a different ease when hiding the items, you should just create a new animation in that if/else. if (self.isActive) { gsap.to(boxes, { overwrite: true, ease: "back.out", // or whatever exit ease you want y: -64, opacity: 0, stagger: { amount: 0.25 } }); } else { gsap.to(boxes, { overwrite: true, ease: "back.out", y: 0, opacity: 1, stagger: { amount: 0.25 } }); } Multiple GSAP Animations in React (codepen.io)
  2. Actually it looks like it doesn't like interrupting the tween fired in the leave event. I can't use xTo for that because it has a dynamic ease applied. I wonder why it doesn't overwrite it.
  3. The default of overwrite: false is the most CPU-friendly option...it assumes you're responsible with the way you create your animations (not creating conflicts). 2nd fastest is overwrite: true because that doesn't have to care about which properties - it just obliterates any active tweens of the same object. We don't plan on changing any of those overwrite options if that's what you're asking. It won't cause a conflict, no - the whole purpose is to avoid conflicts But I think it'd be rather strange to do physics animations with overwrite: "auto" but it's not wrong or anything. Frankly, you're not going to notice a performance difference unless you really push things hard and have hundreds/thousands of things initiating animations simultaneously. And remember, overwriting logic only runs ONCE for a tween (when it renders for the first time). It's not like it's constantly draining resources looking for things to overwrite. As you probably know, we put a lot of effort into making GSAP highly performant. I may be misunderstanding but no, I don't see any reason to use isTweening() in that scenario. Here's some very basic pseudo code: // this replaces your setTimeout() logic. Just use a delayedCall - remember, it's just a tween with an onComplete, so you can pause()/restart() it. let hideControlsDelay = gsap.delayedCall(1, hideControls).pause(); function onPointerEnter() { hideControlsDelay.pause(); // don't hide controls when the pointer is over them gsap.to(controls, {autoAlpha: 1, overwrite: true}); // animate controls in } function onPointerLeave() { hideControlsDelay.restart(true); } function hideControls() { gsap.to(controls, {autoAlpha: 0, overwrite: true}); // animate controls out } hitArea.addEventListener('mouseenter', onPointerEnter); hitArea.addEventListener('mouseleave', onPointerLeave); I guess I don't really understand why isTweening() would be helpful. Maybe I'm missing something. Anyway, does that help?
  4. I didn't totally follow your explanation there, @mjray, but my guess is that you were creating conflicting tweens. Did you try simply setting overwrite: true or overwrite: "auto" on your animation? Also, did you know about this method?: https://greensock.com/docs/v3/Plugins/ScrollTrigger/labelToScroll() It's relatively new.
  5. Welcome to the forums, @Sooova. Would you please provide just a minimal demo that more clearly demonstrates the issue? I'm pretty lost when I look at that demo, especially with all the missing images. You can just use simple colored <div> elements instead maybe. It shouldn't take 100+ lines of code to show the issue. There are a lot of setTimeouts/Promises and delays and stacked up strings of logic - perhaps you could just eliminate any randomization, isolate a single state change of one or two elements, and only focus on that in your demo(?) And please keep in mind that these forums aren't really for general troubleshooting of logic issues, but we're happy to answer any GSAP/Flip questions. A few quick comments: I assume this was a mistake: // BAD onComplete: isComplete(), // <- executes immediately and assigns whatever isComplete returns to the onComplete. // GOOD onComplete: isComplete, And this: // BAD overwrite: "false", // GOOD overwrite: false, You can use gsap.utils.random() instead of your getRandomInt() function.
  6. We love helping with GSAP-related questions, but unfortunately we just don't have the resources to provide free general consulting, logic troubleshooting, or "how do I recreate this cool effect I saw on another site?" tutorials. Of course anyone else is welcome to post an answer if they'd like - we just want to manage expectations. If I were you I'd approach this with single tweens per box and overwrite:true or auto. Maybe just focus on trying to swop one box between two different directions without scrollTrigger, then add some more boxes, then add in a ScrollTriggers with some callbacks and swop the direction over in the callbacks. Timelines are pre-calculated and a little less flexible for this sort of thing whereas tweens can be a bit more dynamic. Hope this helps a bit!
  7. Here's how I'd simplify it: https://codepen.io/GreenSock/pen/ExEZxOz?editors=0010 document.addEventListener("keyup", function(e) { let x, y; if (e.keyCode == 37) { // left arrow x = 100; } else if (e.keyCode == 38) { // up arrow y = 100; } else if (e.keyCode == 39) { // right arrow x = -100; } else if (e.keyCode == 40) { // down arrow y = -100; } if (x || y) { // if anything changed... let vars = {overwrite: true}; if (x) { vars.x = gsap.utils.clamp(bigDraggable.minX, bigDraggable.maxX, gsap.getProperty(bigImage, "x") + x); } else { vars.y = gsap.utils.clamp(bigDraggable.minY, bigDraggable.maxY, gsap.getProperty(bigImage, "y") + y); } gsap.to(bigImage, vars); e.preventDefault(); } }); Does that help?
  8. Hey GSAP, first: you are awesome, thank you for these supercool libaries. We want to try out the new ScrollSmoother an got stuck on the following problem: We have a transform based animation with a scrollTrigger: let tl = gsap.timeline({ scrollTrigger:{ trigger: card, start: "top top", end: "bottom top", pinSpacing: false, pin: true, scrub: true, markers: false, }, defaults: { overwrite: "auto"} }); tl.fromTo(cardContent, {scale:1, opacity:1}, {scale: 0.8, opacity: 0.2}); tl.to(cardContent, {opacity:0}); To avoid conflicts with the transform values in the parent container animation (like "jumping" elements) , we use clearProps: true on the parent containers animation. This works like a charm, BUT: with using ScrollSmoother, the same effect of "jumping" elements ist back, as ScrollSmoother is based on transforms. I'm happy for any advice on how to deal with that. Thanks
  9. Hi there! I have an issue using gsap. I'm using chakra and next on my project and i dont know why, but when I put the gsap to work it just make my svg weird, It look to overwrite something that should not happen. If you look at this little example and comment the line of useEffect you'll see what I mean. Hopeful for help, thanks https://codesandbox.io/s/portfolio-app-forked-20tos8?file=/components/projects.js
  10. The main problem is that you keep creating a new tween every single time there's a mousemove event and also every time there's a mouseenter but you never set an overwrite nor do you kill() the old tween(s). So, for example, you create a repeating backgroundPosition tween the first time the user's mouse enters and then the next time you create a new one but the OLD one is continuing to play and repeat over and over. That tween is affecting the backgroundPosition as well (you're creating a bunch of conflicting tweens). You could just set overwrite: "auto" on your tween(s) but I'd actually recommend simply reusing a single tween instance rather than creating new ones over and over and over again. That'll perform better. https://codepen.io/GreenSock/pen/podNjwp?editors=0010 You had a few typos in there too. Is that CodePen more like what you wanted?
  11. Thank You Cassie and Jack, there's of course some problem on the logic I'm pursuing, I know that the height of the page plays a key role on the animation I'm working on so I ask u this: if you were to make this animation from that I tried to explain the beginning, where would you start from? I don't want to bang my head unnecessarily If u think there's a better way to approach this animation I'm all ears The only caveat is that the two divs must be 100vh, always, at least when they're visible. (I tried with observer, it seems more fitting but I'm having similar problems with the changing page height Observer.create({ target: window, type: "wheel,touch,scroll", onUp: () => { move('100vh') }, onDown: () => { move(0) } }); function move(value) { gsap.to("#bottom", { "top": value, duration: 1.3, ease: Quart.easeInOut, // overwrite:true }) } )
  12. Upgrading your project from using GSAP 2 to GSAP 3? It's easy. Most legacy code is already 100% compatible, but there are a few key differences to keep in mind. This guide will help move from GSAP 1.x/2.x to the all-new (and very exciting) GSAP 3. Quick links: New Tween/Timeline Syntax Duration Easing Staggers Overwriting Plugins Cycle Ticker Defaults Callback scope ThrowPropsPlugin renamed InertiaPlugin Other things to keep in mind Frequently Asked Questions More information New Tween/Timeline Syntax (optional) The old syntax still works, but technically you never need to reference TweenMax, TweenLite, TimelineMax or TimelineLite anymore because they're all simplified into a single gsap object! // old TweenMax.to(".class", 2, {x: 100}); // new gsap.to(".class", {duration: 2, x: 100}); // -- Timelines -- // old var tl = new TimelineMax(); // new var tl = gsap.timeline(); Notice there's no "new" keyword needed to create the timeline. Internally, there's one "Tween" class (replaces TweenLite/TweenMax) and one "Timeline" class (replaces TimelineLite/TimelineMax), and both have all of the features like repeat, yoyo, etc. When you call one of the gsap methods like .to(), .from(), etc., it returns an instance of the appropriate class with easily chainable methods. You never need to wonder which flavor (Lite/Max) you need. So for the vast majority of your code, you could simply replace TweenLite and TweenMax with "gsap". You could also do a search/replace for "new TimelineLite(" and "new TimelineMax(", replacing them with "gsap.timeline(" (notice we left off the closing ")" so that any vars objects are retained, like if you had "new TimelineMax({repeat:-1})" it'd keep the repeat). Duration (optional) You can still define a tween's duration as the 2nd parameter, but in GSAP 3 we encourage you to define it inside the vars object instead because it's more readable, it fits with the new keyframes feature, and can be function-based: // old TweenMax.to(obj, 1.5, {...}); TweenMax.from(obj, 1.5, {...}); TweenMax.fromTo(obj, 1.5, {...}, {...}); // new gsap.to(obj, {duration: 1.5, ...}); gsap.from(obj, {duration: 1.5, ...}); gsap.fromTo(obj, {...}, {duration: 1.5, ...}); Easing (optional) The old eases still work great, but you can switch to the new, more compact ease format that requires less typing, is more readable, and eliminates import hassles. Simply include the ease name (all lowercase) followed by a dot and then the type (".in", ".out", or ".inOut"). Note that .out is the default so you can omit that completely. // old ease: Power3.easeInOut ease: Sine.easeOut ease: Linear.easeNone ease: Elastic.easeOut.config(1, 0.5) ease: SteppedEase.config(5); // new ease: "power3.inOut" ease: "sine" // the default is .out ease: "none" // shortened keyword ease: "elastic(1, 0.5)" ease: "steps(5)" Notice that for eases that support additional inputs, simply put them within some parenthesis at the end: // old ease: Elastic.easeOut.config(1, 0.3) ease: Elastic.easeIn.config(1, 0.3) // new ease: "elastic(1, 0.3)" // the default is .out ease: "elastic.in(1, 0.3)" RoughEase, SlowMo, and ExpoScaleEase are not included in the core GSAP file - they're in an external EasePack file. We highly recommend using our Ease Visualizer to get the exact ease that you want and easily copy the correct formatting. Staggers (optional) The old stagger methods still exist for legacy code, but GSAP 3 supports staggers in ANY tween! Simply use the stagger property within the vars parameter. // old TweenMax.staggerTo(obj, 0.5, {...}, 0.1); // new // Simple stagger gsap.to(obj, {..., stagger: 0.1}); // Complex stagger gsap.to(obj, {..., stagger: { each: 0.1, from: "center" grid: "auto" }}); Caveat: the old TweenMax.stagger* methods returned an Array of tweens but the GSAP 3 legacy version returns a Timeline instead. So if you have code that depends on an array being returned, you'll need to adjust your code. You can use getChildren() method of the resulting timeline to get an array of nested tweens. Handling repeats and onComplete: if you add a repeat (like repeat: -1) to a staggered tween, it will wait until all the sub-tweens finish BEFORE repeating the entire sequence which can be quite handy but if you prefer to have each individual sub-tween repeat independently, just nest the repeat INSIDE the stagger object, like stagger: {each: 0.1, repeat: -1}. The same goes for yoyo and onComplete. To learn more about staggers, check out this article. See the Pen Staggers demo by GreenSock (@GreenSock) on CodePen. Overwriting Prior to GSAP 3, the default overwrite mode was "auto" which analyzes the tweens of the same target that are currently active/running and only overwrites individual properties that overlap/conflict, but in GSAP 3 the default mode is false meaning it won't check for any conflicts or apply any overwriting. Why? The overwrite behavior sometimes confused people, plus it required extra processing. We wanted to streamline things in GSAP 3 and make overwriting behavior an opt-in choice. To get the GSAP 1.x/2.x behavior, simply do this once: // set the default overwrite mode to "auto", like it was in GSAP 1.x/2.x gsap.defaults({overwrite: "auto"}); Of course you can set overwrite on a per-tween basis too (in the vars object). Also note that there were more overwrite modes in GSAP 1.x/2.x (like "concurrent", "preexisting" and "allOnStart") that have been eliminated in GSAP 3 to streamline things. Now the only options are "auto" (isolates only specific overlapping/conflicting properties), false (no overwriting), or true (when the tween starts, it immediately kills all other tweens of the same target regardless of which properties are being animated). onOverwrite was removed in favor of a new onInterrupt callback that fires if/when the tween is killed before it completes. This could happen because its kill() method is called or due to overwriting. Plugins Loading plugins Similar to the old TweenMax, some plugins are already included in GSAP's core so that they don't need to be loaded separately. These are called core plugins and include AttrPlugin, CSSPlugin, ModifiersPlugin, and SnapPlugin. RoundPropsPlugin is also included for legacy code, but it has been replaced by the more flexible SnapPlugin. Other plugins, such as Draggable, MotionPathPlugin, MorphSVGPlugin, etc. need to be loaded separately and registered using gsap.registerPlugin(). We recommend using the GSAP Installation Helper to get sample code showing how to load and register each file. // register plugins (list as many as you'd like) gsap.registerPlugin(MotionPathPlugin, TextPlugin, MorphSVGPlugin); MotionPathPlugin replaces BezierPlugin GSAP's new MotionPathPlugin is essentially a better, more flexible version of the older BezierPlugin. In most cases, you can just change bezier legacy references to motionPath: // old bezier: [{x:200, y:100}, {x:400, y:0}, {x:300, y:200}] // new motionPath: [{x:200, y:100}, {x:400, y:0}, {x:300, y:200}] Keep in mind that MotionPathPlugin also supports SVG paths! If you're having trouble converting your bezier curve to a motion path, feel free to post in our forums. See the Pen MotionPathPlugin demo by GreenSock (@GreenSock) on CodePen. The old type: "soft" of BezierPlugin isn't available directly in MotionPathPlugin (it was rarely used), but there's a helper function in this forums post that'll deliver identical results. className tweens removed Support for class name tweens has been removed since they're not very performant, they're less clear, and required an uncomfortable amount of kb. Plus they were rarely used. Just use regular tweens instead that explicitly animate each property. For example if you had this CSS: .box { width: 100px; height: 100px; background-color: green; } .box.active { background-color: red; } You could use this JavaScript: // old .to(".class", 0.5, {className: "+=active"}) // new .to(".class", {backgroundColor: "red"}) // if you need to add a class name in the end, you could do this instead: .to(".class", {backgroundColor: "red", onComplete: function() { this.targets().forEach(elem => elem.classList.add("active")); }}) ColorPropsPlugin unnecessary GSAP 3 has improved support for animating color values built into GSAP's core. As such, the old ColorPropsPlugin isn’t necessary. Simply animate the color values directly as needed! // old TweenMax.to(myObject, 0.5, {colorProps: {borderColor: "rgb(204,51,0)"} }); // new gsap.to(myObject, {borderColor: "rgb(204,51,0)", duration:0.5}); skewType eliminated GSAP 3 removed skewType and CSSPlugin.defaultSkewType because they were rarely used and we wanted to conserve file size. If you still need this functionality, feel free to use the compensatedSkew helper function. suffixMap CSSPlugin.suffixMap has been replaced by setting the units inside of gsap.config() like: // old CSSPlugin.suffixMap.left = "%"; // new gsap.config({units: {"left": "%"}}) Cycle GSAP 2.x stagger methods had a special cycle property that'd allow function-based values or arrays whose values would be cycled through, but GSAP 3 replaces this with a new even more flexible gsap.utils.wrap() utility that can be used in ANY tween, not just staggers! // old TweenMax.staggerTo(".class", 0.5, {cycle: {x: [-100, 100]}}, 0.1) // new gsap.to(".class", {x: gsap.utils.wrap([-100, 100]), stagger: 0.1}) See the Pen GSAP 3 wrap() and wrapYoyo() utilities demo by GreenSock ( @GreenSock) on CodePen. Ticker If you want a function to run every time that GSAP updates (typically every requestAnimationFrame), simply add a listener to gsap.ticker with the new, simpler syntax: // old TweenLite.ticker.addEventListener("tick", myFunction); TweenLite.ticker.removeEventListener("tick", myFunction); // new gsap.ticker.add(myFunction); gsap.ticker.remove(myFunction); Note that there is no .useRAF() function. GSAP 3 always uses requestAnimationFrame unless it is not supported, in which case it falls back to setTimeout. Defaults Setting global defaults has been greatly simplified in GSAP 3. Instead of having static defaults (like TweenLite.defaultEase, TweenLite.defaultOverwrite, CSSPlugin.defaultTransformPerspective, and CSSPlugin.defaultSmoothOrigin), there is now one simple method where you can set all of these defaults: gsap.defaults(). gsap.defaults({ ease: "power2.in", overwrite: "auto", smoothOrigin: false, transformPerspective: 500, duration: 1 }); You can also set defaults for each timeline instance which will be inherited by child tweens: var tl = gsap.timeline({defaults: { ease: "power2.in", duration: 1 } }); // now tweens created using tl.to(), tl.from(), and tl.fromTo() will use the // above values as defaults Other configuration values that aren't tween-specific can be set using gsap.config() including what was formerly set using properties like TweenLite.autoSleep and CSSPlugin.defaultForce3D. gsap.config({ autoSleep: 60, force3D: false, nullTargetWarn: false, units: {left: "%", top: "%", rotation: "rad"} }); Callback scope In GSAP 3 scoping has been simplified. There is no more "scope" parameter in various methods like timeline's call() method, and no more onUpdateScope, onStartScope, onCompleteScope, or onReverseCompleteScope. Instead, use callbackScope to set the scope of all of the callback scopes of a particular tween/timeline or use .bind to set the scope of particular callbacks: // old TweenMax.to(obj, 0.5, {..., onCompleteScope: anotherObj, onComplete: function() { console.log(this); // logs anotherObj }}); // new gsap.to(obj, {..., callbackScope: anotherObj, onComplete: function() { console.log(this); // logs anotherObj } }); // or gsap.to(obj, {..., onComplete: function() { console.log(this); // logs anotherObj }.bind(anotherObj) }); You can access the tween itself by using this inside of the callback. In GSAP 1.x/2.x, you could reference a special "{self}" value in onCompleteParams, for example, but that's no longer valid because the callback is scoped to the tween instance itself by default. So, for example, you can get the tween's targets by using this.targets(). For example: // old TweenMax.to(obj, 0.5, {onComplete: function() { console.log(this.target); }}); // new gsap.to(obj, {onComplete: function() { console.log(this.targets()); // an array }}); If this.targets is undefined, it's probably because you're using an arrow function which always locks its scope to where the arrow function was originally declared. If you want "this" to refer to the tween instance, just use a normal function instead of an arrow function. gsap.to(".class", { // BE CAREFUL! Arrow functions lock scope to where they were created, so "this" won't refer to the tween instance here! // Use normal functions if you need "this" to refer to the tween instance. onComplete: () => console.log(this.targets()) // will not work }); If you prefer using arrow functions (to lock scope to your object/context) and need to reference the tween instance in your callback, you could use this helper function: // this function will always push the tween instance into the parameters for you and allow you to define a scope. function callback(func, scope, params) { let tween; params = params || []; return function() { if (!tween) { tween = this; params.push(tween); } func.apply(scope || tween, params); }; } And then you could use it like this: gsap.to(... { onComplete: callback(tween => { console.log(this); // since this is an arrow function, scope is locked anyway so this is your class instance console.log(tween); // tween instance }) }); ThrowPropsPlugin renamed InertiaPlugin ThrowPropsPlugin has been renamed InertiaPlugin and has some new features. Other things to keep in mind Transforms We recommend setting all transform-related values via GSAP to maximize performance and avoid rotational and unit ambiguities. However, since it's relatively common for developers to set a value like transform: translate(-50%, -50%) in their CSS and the browser always reports those values in pixels, GSAP senses when the x/y translations are exactly -50% in pixels and sets xPercent or yPercent as a convenience in order to keep things centered. If you want to set things differently, again, just make sure you're doing so directly through GSAP, like gsap.set("#id", {xPercent:0, x:100, yPercent:0, y:50}). Getting an object's properties In GSAP 1.x/2.x, it was relatively common for developers to access an element's transform-specific properties via the undocumented _gsTransform object but in GSAP 3 it's much easier. gsap.getProperty() lets you get any property, including transforms. There is no more _gsTransform. // old element._gsTransform.x // new gsap.getProperty(element, "x") Referring to the core classes If you need to refer to the core Tween or Timeline class, you can do so by referencing gsap.core.Tween and gsap.core.Timeline. timeScale() and reversed() In GSAP 3 the timeScale controls the direction of playback, so setting it to a negative number makes the animation play backwards. That means it is intuitively linked with the reversed() method. If, for example, timeScale is 0.5 and then you call reverse() it will be set to -0.5. In GSAP 2 and earlier, the "reversed" state of the animation was completely independent from timeScale (which wasn't allowed to be negative). So in GSAP 3, you could even animate timeScale from positive to negative and back again! Removed methods/properties TweenLite.selector - There's no more TweenLite.selector or TweenMax.selector (it's pointless with document.querySelectorAll() that's in browsers now). timeline.addCallback() - dropped in favor of the simpler .call() method. TweenMax's pauseAll(), resumeAll(), killAll(), and globalTimeScale() - dropped in favor of directly accessing methods on the globalTimeline, like: gsap.globalTimeline.pause(); gsap.globalTimeline.resume(); gsap.globalTimeline.clear(); // like killAll() gsap.globalTimeline.timeScale(0.5); Frequently Asked Questions (FAQ) Why migrate to GSAP 3? GSAP 3 is almost half the file size of the old TweenMax, has 50+ more features, and has a simpler API. See the "Top 5 Features of GSAP 3" article for more information. Do I have to use the new syntax? We highly recommend that you use the new syntax, but no, it's not imperative. Most old GSAP syntax will work just fine in GSAP 3. We're pretty confident that you'll love the new syntax once you're used to it! Will GSAP 2.x be actively maintained for years? We'll certainly answer questions in the forums and help users of GSAP 2.x, but we're focusing all of our development resources on the more modern 3.x moving forward so don't expect any additional 2.x releases in the future. My production build isn't working with GSAP 3. Why? Usually this just means that your build tool is applying tree shaking and dumping plugins - that's why you need to register your plugins with gsap.registerPlugin(). We recommend that you use the Installation Helper which gives you code for proper registration as well. I am seeing some odd/unexpected behavior but don't have any errors. What's going on? Try setting gsap.defaults({overwrite: "auto"}) and see if that fixes the issue. If it does, you must have created some conflicting tweens. You could either keep the default overwrite value of "auto" or restructure your animation to avoid the conflict. If that doesn't fix the issue, please post in our forums and we'd be happy to help! More information For a deep dive into the nitty-gritty of GSAP 3, check out the GSAP 3 Release Notes. As always, if you have questions or are having trouble our forums are available to help you!
  13. Sure, if you're just staggering them (same animation for all, just offset), you can simply use a "stagger" on a single tween. No need for a timeline. But yes, if you need to animate various things differently, you can absolutely use a timeline that you create in the callback(s). Just make sure you set overwrite: true (or "auto") on the tweens to ensure you don't create conflicts. onEnter: () => { let tl = gsap.timeline({defaults: {overwrite: true}}); tl.to(...).to(...)... } If you're still struggling, please provide a minimal demo and we'd be happy to take a peek. Good luck!
  14. Nope, that's fine because GSAP sets inline styles for maximum specificity. The only other thing I can think of is if maybe you accidentally killed the opacity animation? Like if after creating it, you did a DIFFERENT animation on that same element and set overwrite: true? I doubt it, but I'm just brainstorming. I would recommend setting an onUpdate on that particular tween so you know when it's being updated, and then open up Dev Tools and scroll to where it should be animating opacity and look in the console to see if it's firing. .to("#header-copy", { onUpdate: () => console.log("updated!"), opacity: 1, ease: "power1.inOut", duration: 30, }, 70); And is the opacity sticking at 0 or is it at 1 the whole time? I wonder if maybe it was not 0 when the tween rendered the first time, thus it's animating from 1 to 1 (no change).
  15. GSAP Helper

    Animated cursor

    We love helping with GSAP-related questions, but unfortunately we just don't have the resources to provide free general consulting and logic troubleshooting. Of course anyone else is welcome to post an answer if they'd like - we just want to manage expectations. You need to adjust your value on scroll. You could do that in a "scroll" event handler and look at the deltaY of the event perhaps. I would also strongly recommend using the gsap.quickTo() for your tweens that are constantly getting recreated on each mousemove event. The way you've got them set up now, you're creating new instances every time and they're all conflicting with each other because you didn't set overwrite: true (or "auto"). That's bad for performance. You can post in the "Jobs & Freelance" forum for paid consulting, or contact us directly. Otherwise, if you've got a GSAP-specific question, we'd be happy to try to help with that.
  16. That code/logic looks very strange to me. I suspect @SteveS is correct, that you're overcomplicating and over-engineering things. You've got an onUpdate that's handling things differently based on the progress (odd - it's probably much cleaner to just use two ScrollTriggers) and then if it's more than 25%, you're calling moveAnimate() on EVERY update, over and over again which is creating a new tween each time and there's no overwrite set, so you're creating a ton of conflicting tweens that are all trying to control the same properties of the same elements. That's definitely a problem. The same goes for your xPercent tween in there - you're creating a new one over and over again. If you still need some help, I'd strongly recommend just simplifying things using a few colored <div> elements in CodePen and then post back here with your GSAP-specific question and we'd be happy to take a peek.
  17. I'm still pretty fuzzy on what you're asking here, but here are a few comments in case they're helpful: When you set overwrite: true on a tween, that overwriting logic only runs ONCE, immediately when you create the tween. It basically says "find all other tweens of the same target and kill them right now." With overwrite: "auto", it runs once the first time the animation renders and it finds only other active tweens of the same target(s) and kills only the individual conflicting properties. It would be very very bad for performance if it tried to run the overwrite logic every single time that animation rendered/played. We obsess about performance around here because animation is the most performance-sensitive part of UX. It sounds like maybe you're expecting that every time you .play() one timeline, it will kill any other timelines but that is NOT true. When something is overwritten, it's dead. Gone. It doesn't come back later. The first time a tween renders, it records the start/end values so that it can very quickly interpolate between them. Again, that happens ONCE. It sounds like you might be expecting that to happen every time you play() a timeline. So, for example, if box.x is 0 and then you have a .to(box, {x: 100}) in a timeline, the first time it renders it will record "okay, we're going from 0 to 100. Lock that in". So now every time that timeline plays again, it ALWAYS goes from 0 to 100. However, let's say you set box.x to 200 somewhere else in your code and then you .play() this timeline again - you shouldn't expect it to animate from 200 to 100 (instead of 0 to 100) because it already locked in the starting value of 100. You can .invalidate() a tween/timeline to force it to flush any pre-recorded values and then it'll re-record them the next time it renders. If you have multiple timelines that affect the same properties of the same targets, you can easily prevent them from conflicting by calling .pause() on the ones that shouldn't be playing, and .play() the one that should. Again, if you want them to flush any recorded starting values, just call .invalidate(). I cannot imagine why it would take days to set up a minimal demo - all we need is the most basic possible illustration. Hopefully that wouldn't take more than 10 minutes. Maybe 2 buttons and 2 timelines with a couple of tweens in each that affect a single <div> or something(?) We're eager to help and I'm sure that minimal demo will go a long way to allowing us to get you the answer you're looking for.
  18. You definitely shouldn't be using WebKitCSSMatrix like that - it would be much cleaner (and more compatible) to use a simple gsap.getProperty(".ticker-wrapper", "x") but you don't even need to do that. Here's a different approach that leverages a simple xPercent animation: https://codepen.io/GreenSock/pen/rNwaLvw?editors=0010 $(document).ready( function(){ $('ul li').wrapAll('<span class="ticker-items">'); var tickerWidth = $('ul').width(); var spanWidth = $('ul span').width(); $('ul span').clone().appendTo('ul'); $('ul span').wrapAll('<span class="ticker-wrapper">'); var speed = 50, tl = gsap.timeline(); tl.fromTo(".ticker-wrapper", { // intro (from far right edge) xPercent: tickerWidth / spanWidth / 2 * 100 }, { xPercent: 0, duration: tickerWidth / speed, ease: "none" }).to(".ticker-wrapper", { // loop xPercent: -50, ease: "none", duration: spanWidth / speed, repeat: -1 }); $('ul').on('mouseenter', () => gsap.to(tl, {timeScale: 0, overwrite: true})); $('ul').on('mouseleave', () => gsap.to(tl, {timeScale: 1, overwrite: true})); }); Notice that in the mouseenter/mouseleave I'm actually animating the timeScale of the timeline so that it gradually slows down or speeds up instead of suddenly stopping/starting. I just think that feels nicer, but you're welcome to do a simple tl.pause() and tl.play() if you prefer. However, I think the problem you mentioned in your previous post has to do with the fact that only one clone is done in that code because it assumes your content fills the container. You could add a loop in there to clone it multiple times but I was inspired to create a gsap.effect.ticker that should help with this: https://codepen.io/GreenSock/pen/rNwaMPo?editors=0010 gsap.registerEffect({ name: "ticker", effect(targets, config) { let master = gsap.timeline(); buildTickers(targets, config); function clone(el) { let clone = el.cloneNode(true); el.parentNode.insertBefore(clone, el); clone.style.position = "absolute"; return clone; } function nestChildren(el, className) { let div = document.createElement("div"); while (el.firstChild) { div.appendChild(el.firstChild); } el.appendChild(div); className && div.setAttribute("class", className); div.style.display = "inline-block"; div.style.boxSizing = "border-box"; return div; } function buildTickers(targets, config, isResize) { if (isResize) { // on window resizes, we should delete the old clones and reset the widths targets.clones.forEach(el => el && el.parentNode && el.parentNode.removeChild(el)); gsap.set(targets.chunks, {x: 0}); } else { targets.clones = []; targets.chunks = []; } master.clear(); let clones = targets.clones, chunks = targets.chunks; targets.forEach((el, index) => { let chunk = chunks[index] || (chunks[index] = nestChildren(el, config.className)), chunkWidth = chunk.offsetWidth + (config.padding || 0), cloneCount = Math.ceil(el.offsetWidth / chunkWidth), chunkBounds = chunk.getBoundingClientRect(), elBounds = el.getBoundingClientRect(), right = (el.dataset.direction || config.direction) === "right", tl = gsap.timeline(), speed = parseFloat(el.dataset.speed) || config.speed || 100, i, offsetX, offsetY, bounds, cloneChunk, all; el.style.overflow = "hidden"; gsap.getProperty(el, "position") !== "absolute" && (el.style.position = "relative"); // avoid scrollbars for (i = 0; i < cloneCount; i++) { cloneChunk = clones[i] = clone(chunk); if (!i) { bounds = cloneChunk.getBoundingClientRect(); offsetX = bounds.left - chunkBounds.left; offsetY = bounds.top - chunkBounds.top; } gsap.set(cloneChunk, {x: offsetX + (right ? -chunkWidth : chunkWidth) * (i + 1), y: offsetY}); } all = clones.slice(0); all.unshift(chunk); tl.fromTo(all, { x: right ? "-=" + (chunkBounds.right - elBounds.left) : "+=" + (elBounds.right - chunkBounds.left) }, { x: (right ? "+=" : "-=") + elBounds.width, ease: "none", duration: elBounds.width / speed, overwrite: "auto" }).to(all, { x: (right ? "+=" : "-=") + chunkWidth, ease: "none", duration: chunkWidth / speed, repeat: -1 }); master.add(tl, 0); }); // rerun on window resizes, otherwise there could be gaps if the user makes the window bigger. isResize || window.addEventListener("resize", () => buildTickers(targets, config, true)); } return master; } }); Once that effect is registered, all you have to do is: let tl = gsap.effects.ticker(".ticker", { speed: 100, className: "ticker-content", //direction: "right" }); So you can tweak the speed, direction, and the class name that's added to the wrapper <div> elements around the chunks. It dynamically figures out how many clones to make. It even handles resizes. You can even add data-speed or data-direction attributes to the elements instead of passing that in through the config object. I hope that helps!
  19. That's because you're creating a bunch of conflicting tweens that are fighting with each other for control on every mousemove event. Just set overwrite: true on your line tweens and that fixes it.
  20. Hm, it sounds like there may be some logic flaws in your code, but it's difficult to troubleshoot without a minimal demo. But I'll offer a few thoughts: It looks like you're reusing the same timeline instance over and over again and doing a clear() after it's done. That's not "wrong", but it's probably simpler to just create a new timeline each time (or if you're not sequencing things or need to control multiple as a whole, just skip the timeline altogether and use tweens). Remember that by default, when you add() something to the timeline, it gets added to the END of it. So let's say the user clicks multiple times quickly, that means your code is just sequencing the new ones after the current ones that haven't finished yet. See the problem? Or do you clear() it before running each time too? Again, it's tough to know by just looking at a small excerpt. You don't need to timeline.add(gsap.to(...)) - that's just a long way of using the convenience methods: // long timeline.add( gsap.to( ... )); // short timeline.to(...); Be careful about creating conflicting tweens where they're fighting to control the same property of the same object. You can set overwrite: true to have GSAP immediately kill all other tweens of those targets, or overwrite: "auto" to only kill the individual parts (properties) of the tweens that overlap. I'd rewrite your first block of code like this: // OLD let itemScrollTimeLine = gsap.timeline({ paused: true, onComplete: resetTimeline }); function resetTimeline() { console.log('Completed'); itemScrollTimeLine.clear(); } if (itemList.indexOf(elem.id) >= 0) { let elemPos = (window.innerHeight - document.getElementById(elem.id).offsetHeight) / 2; itemScrollTimeLine.add(gsap.to(window, { duration: 1.2, ease: "power1.inOut", scrollTo: { y: elem, offsetY: elemPos } })); } else { itemScrollTimeLine.add(gsap.to(window, { duration: 1.2, ease: "power1.inOut", scrollTo: { y: elem, offsetY: 100 } })); } itemScrollTimeLine.add(gsap.to(elem, { ease: "power3.inOut", duration: 0.8, '--line-color-top': '#a18248' }), '>'); // NEW let itemScrollTimeLine = gsap.timeline(); itemScrollTimeLine.to(window, { duration: 1.2, ease: "power1.inOut", overwrite: "auto", scrollTo: { y: elem, offsetY: itemList.indexOf(elem.id) >= 0 ? (window.innerHeight - document.getElementById(elem.id).offsetHeight) / 2 : 100 } }); itemScrollTimeLine.to(elem, { ease: "power3.inOut", overwrite: "auto", duration: 0.8, '--line-color-top': '#a18248' }); You really shouldn't need to getChildren() and remove() any of them. Ditch that altogether. I think that was more of a band-aid that was attempting to cover over the fundamental problem which had more to do with your reusing the same timeline and continuing to shove new tweens one-after-the-other or maybe overwriting (or lack thereof). If you're still having trouble, it'll greatly increase your chances of getting a solid answer if you can provide a minimal demo. Thanks for being a Club GreenSock member! 🙌 Happy tweening!
  21. Actually overwrite:auto is kinda easy than what akapowl but I think it necessarry to do that hahaaha..Thanks @akapowl @GreenSock
  22. Hi, I am trying to repeat my timeline. The timeline plays perfect, but just one time. Please, can somebody please take a look at my code to see if there is any problems. import com.greensock.*; import com.greensock.easing.* mcText._alpha = 0; mcButton._alpha = 0; mcLegal._alpha = 0; mcPlaneicon._alpha = 0; mcPlaneicon2._alpha = 0; mcPlaneicon3._alpha = 0; mcPlaneicon4._alpha = 0; mcAmsterdamicon._alpha = 0; mcParisicon._alpha = 0; mcParis._alpha = 0; mcAmsterdam._alpha = 0; mcPriceamsterdam._alpha = 0; mcPriceparis._alpha = 0; var tl = new TimelineMax({repeat:2}); tl.add( TweenLite.to(mcAmsterdam, 0.3, {_alpha:90, delay:1, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcAmsterdamicon, 0.3, {_alpha:90, delay:1.4, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcPlaneicon2, 0.3, {_alpha:90, delay:1.8, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcPriceamsterdam, 0.3, {_alpha:90, delay:2.2, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcLegal, 0.5, {_alpha:100, delay:2.2, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcAmsterdamicon, 0.3, {_alpha:0, delay:5, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcAmsterdam, 0.3, {_alpha:0, delay:5, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcPriceamsterdam, 0.3, {_alpha:0, delay:5, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcPlaneicon2, 0.3, {_alpha:0, delay:5, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcBg, 0.3, {_x:-1920, delay:5.2, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcParis, 0.3, {_alpha:90, delay:5.8, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcParisicon, 0.3, {_alpha:90, delay:6.2, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcPlaneicon3, 0.3, {_alpha:90, delay:6.6, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcPriceparis, 0.3, {_alpha:90, delay:7, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcParisicon, 0.3, {_alpha:0, delay:10.2, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcParis, 0.3, {_alpha:0, delay:10.2, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcPriceparis, 0.3, {_alpha:0, delay:10.2, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcPlaneicon3, 0.3, {_alpha:0, delay:10.2, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcLegal, 0.5, {_alpha:0, delay:10.2, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcText, 0.3, {_alpha:100, delay:10.7, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcPlaneicon4, 0.3, {_alpha:90, delay:11.1, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcButton, 0.3, {_alpha:90, delay:11.5, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcButton, 0.3, {_xscale:110,_yscale:110, delay:13, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcButton, 0.3, {_xscale:100,_yscale:100, delay:13.3, ease:Sine.easeIn, overwrite:false}) ); tl.add( TweenLite.to(mcButton, 0.3, {_xscale:110,_yscale:110, delay:14, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcButton, 0.3, {_xscale:100,_yscale:100, delay:14.3, ease:Sine.easeIn, overwrite:false}) ); tl.add( TweenLite.to(mcButton, 0.3, {_xscale:110,_yscale:110, delay:15, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcButton, 0.3, {_xscale:100,_yscale:100, delay:15.3, ease:Sine.easeIn, overwrite:false}) ); tl.add( TweenLite.to(mcBg, 0.3, {_x:0, delay:16, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcText, 0.3, {_alpha:0, delay:16, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcPlaneicon4, 0.3, {_alpha:0, delay:16, ease:Sine.easeOut, overwrite:false}) ); tl.add( TweenLite.to(mcButton, 0.3, {_alpha:0, delay:16, ease:Sine.easeOut, overwrite:false}) );
  23. Hi, I tried to figure it out on my own but I'm stuck. The first two parts of my animation work how I want it to, but the last part doesnt. When i scroll down 50vh, I want the floating animation (rotatesletters) to stop and the shapes stop moving And then when I scroll back to the top of the screen, I want the floating animation (rotatesletters) to start again. I've tried: 1. overwrite: "auto", 2. rotatesletters.pause() 3. functions I've also rewritten the code four different ways I appreciate any help. Thank you
  24. In general, what do GSAP users have in their arsenal to mitigate animations overlapping when users are triggering multiple non-scrubbed ScrollTriggers and/or tweens while scrolling/moving through a site at various speeds. These are what we've come across: Ensure timelines/tweens do not clash (not always simple) --- however, if you're scrolling through several ScrollTriggers, even if you have a delay or long duration between ScrollTriggers, they can clash if the user scrolls too quickly. I don't think this is the case but it appears that tweens/and callbacks can be skipped if the user scrolls too quickly; we've tested this with .set() and .call(). Add OnEnter/OnLeave logic to check if another timeline is "tweening" and then kill the offending timeline gracefully. I'm not seeing any examples of this between multiple ScrollTriggers, but the logic is fairly straightforward although can be extremely convoluted. Set overwrite on your tweens/timelines. I don't think this applies to separate ScrollTriggers --- I've tried multiple ways and haven't seen any affect between ScrollTriggered timelines that clash. I guess how could it; they are separate timelines? Set overflow hidden on the scrolling container so that the user cannot scroll when a tween is occurring; use very sparingly and only in critical areas; best used with a custom scrollbar to remove visual anomalies. Are there any other ways to mitigate clashes between ScrollTriggers and tweens if a user scrolls/moves too quickly through a site? It's not only too quickly in one direction, but when they reserve direction is when we probably see the most clashing. Is there a default overwrite setting that will have an effect between ScrollTriggered timelines? Does the overwrite already do this and we're just not seeing it/using it correctly? Kind Regards, Nitro Interactive
  25. It'd definitely help to see a minimal demo so we can make sure we're addressing the real issue adequately, but here are some thoughts: If you've built a page in a way that requires that one ScrollTrigger-based animation finishes before another one starts (thus it looks weird if the user scrolls fast and they're both playing), you can force the previous one to completion with a callback: let anim1 = gsap.to(... { scrollTrigger: { onEnterBack: () => anim2.progress(0) } }); let anim2 = gsap.to(... { scrollTrigger: { onEnter: () => anim1.progress(1), onEnterBack: () => anim3.progress(0) } }); let anim3 = gsap.to(... { scrollTrigger: { onEnter: () => anim2.progress(1) } }); Overwriting Keep in mind that overwrite logic runs once: overwrite: true - immediately when the tween is created overwrite: "auto" when the tween renders for the first time And when overwriting occurs, it is permanent. So this is not ideal for what you're talking about because you don't actually want to kill...as in dead...permanently. You're just wanting the animation to finish right away, correct? That's why I suggested the code above. For the record, the reason overwriting occurs once (not every time the animation plays) is for performance reasons and because it's almost never helpful to run more than the first time. We're VERY performance-minded. If you're still struggling, please provide a minimal demo and we'd be happy to take a peek.