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. Hi all, I'm having issues with a simple GSAP3 tween code that I use inside an Adobe Animate banner. I have a movieclip that has a simple scaling animation that uses Adobe Timeline. Now, I want that movieclip to scale using GSAP 3 so I wrote a code right after the Timeline animation. The issue is that, the GSAP3 tween doesn't work but it only works when the code is in the last frame of the Adobe Timeline. I've also tried adding overwrite: true but it doesn't work.. I thought maybe I am missing some options that I need to add on my GSAP3 tween. You can check out my simple demo file attached. Thanks in advance! GSAP 3 Scale.zip
  2. It looks to me like the problem is the fact that you're creating conflicting tweens and the "mouseEnter" animation is LONGER (0.3) than the "mouseLeave" (0.2), thus if you move fast enough, you could create a situation where the "mouseLeave" animation ends BEFORE the "mouseEnter" one does, thus the "mouseEnter" renders last. By default, overwrite is false. You could simply set overwrite:"auto" but if you want absolute best performance you could manage that overwriting manually like this: https://codesandbox.io/s/beautiful-leavitt-7o2tw?file=/src/App.js
  3. Thanks for the explanation. Setting overwrite: true I can still get the animation to go awry on very rare occasions. I've not been able to isolate the exact circumstances and will report back when I do. The manual overwrite approach works perfectly and I've settled on that. Thanks again.
  4. Welcome to the forums, @Olly Grunt. Yeah, that's not a bug - that's just a logic issue on your code. You've got overwrite set to "auto", so each tween will wait to execute any overwriting until the very first time it renders at which point it will look for any other CURRENTLY ACTIVE tweens of the same properties of the same targets and kill just those parts. But you've set up your staggers and delays in a way that makes it pretty easy to create a scenario where the old/stale tweens haven't even started yet when the new tweens render for the first time, so overwriting doesn't occur. Simple solution: set overwrite: true instead of overwrite: "auto". When you set overwrite to true, that IMMEDIATELY kills all animations of the same targets regardless of which properties are getting animated or if those other animations have started yet. There are other solutions too, like you could create a variable to store the current animation (onEnter or onLeave, whichever was last to fire) and simply .kill() that before you create your new tween. That's basically like a manual overwrite system Good luck!
  5. I'm trying to adapt a previous SVG demo... (here) ...to canvas and running into what I believe are fairly basic / newbie issues (both structurally and GSAP-wise). Relevant code begins around line 125 in the demo down below. Questions: Why are the circles tweening back to the bottom? I'm using a gsap.set with overwrite: true so shouldn't that reposition them instantaneously? Likewise, if I change it to a gsap.to and give it a duration (e.g. 10 secs), it will respect that duration. But if I set the duration to 0, it still tweens it as if it were set to 1 second. When I resize the window with the ScrollTrigger enabled, it seems to mess with my debounced resize event. If I comment out the ScrollTrigger, the issue goes away. Is there something I should be doing to avoid this unexpected behavior? I'm sure I'll figure this one out but I thought I'd ask in case it was something simple. Finally, on a structural level, I'm unclear on how to incorporate a ScrollTrigger that updates particle velocity (or timeScale) into this. I don't want to create a new ScrollTrigger every time the draw() or move() method is called. So should I be doing that work inside the ScrollTrigger itself (in an onUpdate)? Or should I be passing ScrollTrigger values into the methods instead? Is there a preferred or recommended style? I've pored over Codepens and this forum but nothing really stands out to me as "obviously correct." I'm trying to emulate as much of Blake's style as possible, but he's a hard act to follow.
  6. You can animate the timeScale of an animation... gsap.to(tl, { overwrite: true, timeScale: 1 }) For ideas on velocity scrolling, this demo might be a good one to learn from. https://codepen.io/GreenSock/pen/eYpGLYL
  7. If I were doing this, I'd probably use a simple function to create a randomized infinitely repeating tween (duration, position) that gets plugged into a timeline and then simply alter the timeScale() of the timeline to make your stuff speed up or slow down. I think that'd be a lot less CPU usage than what you're currently doing with using a modifier on every single element and an onUpdate that's creating a whole new tween every update (don't forget to overwrite: true so you don't end up with a bunch of animations trying to control the same thing). Honestly, I think that's exactly what I'd do. It's not "cheating" - it's a clever problem-solving technique that saves you from having to calculate all those opacity tweens. Is there some reason you don't want to use the current technique? Yes, in my experience <canvas> (especially if it's WebGL-enabled) can render much faster than SVG. Good luck!
  8. GSAP is an animation engine, and doesn't do any rendering. Right now you are using HTML/CSS for rendering. For that warp effect, you would need to use a WebGL renderer like PixiJS or Three.js and probably a custom shader. GSAP could then animate whatever properties your WebGL objects/shader provides. Just follow the first demo you posted. Notice the use of forEach to create a ScrollTrigger for each element, and how it's getting the duration for each element from a data attribute... <div id="del2" class="delayed-section" data-scrub="0.2"> const scrub = gsap.to(imageAnim, { progress: 1, paused: true, ease: "power3", duration: parseFloat(section.dataset.scrub) || 0.1, // <-- reads data-scrub from element overwrite: true }); Using a different duration for each element is what creates the parallax effect.
  9. Hi guys, I am working on a banner animation. I have noticed that when I resize the browser window my video container class does not update. It is understandable because my variables that I passed to scrollTrigger and Timelines are defined once and they keep their values. I have tried to overwrite variables via: document.addEventListener('resize', myCallback) and inside myCallback function I tried to kill() the timelines and run them again but this made duplication of ".pin-spacer" inside a ".pin-spacer" and made a big mess in the DOM. I want to update these variables(videoYShift, videoWidth, videoHeight): searchBannerScrollAnim.to('.search_banner .file_video_wrap', { x: videoXShift, y: -videoYShift, width: videoWidth, height: videoHeight }); My question is what is the valid way to "refresh" the scrollTrigger and Timelines so the video stays centered and responsive on the resize event? The issue is the most visible when you resize the window from your current size to the smaller one. Thank you in advance.
  10. Hi guys! I come humbly in front of you with few drops of hope left, after 5 full days of switching between possible solutions to get a consistent ScrollTrigger behavior on a Gatsby site. Getting directly to you is my last resort, as every google and gsap forum link regarding ScrollTrigger and Gatsby is already visited. 😒 I cannot get a CodePen reproducing the exact issue so I'll try my best to describe it here. Shortly, the problem seems to be, as I suspect, that the ScrollTrigger does not refresh itself when Javascript pops into the browser on top of the SSR-ed html/css bundle. Here's what i did. I created several projects with different versions for dependencies, but i will stick to the simplest one with all dependencies up to date.It's a gatsby with material-ui plugin added, who's exact structure can be found here: https://github.com/mui-org/material-ui/tree/master/examples/gatsby There are no other plugins added, nor any other configs/plugins changed. I rendered the component that will contain the ScrollTrigger (AboutBlock) in the AboutPage page: about.js const AboutPage = () => { return ( <AboutBlock /> ) } export default AboutPage This is the component where i try to animate some elements on reveal when scrolled into view: aboutBlock.js import gsap from "gsap"; import ScrollTrigger from 'gsap/ScrollTrigger'; import animateReveal from "./gs_reveal"; export default function AboutBlock() { gsap.registerPlugin(ScrollTrigger) const revealRefs = useRef([]) revealRefs.current = [] useLayoutEffect(() => { let scrollTriggers = [] scrollTriggers = animateReveal(revealRefs.current) return () => { scrollTriggers.forEach(t => t.kill(true)) } }, []); const addToRevealRefs = el => { if (el && !revealRefs.current.includes(el)) { revealRefs.current.push(el); } }; return ( <Grid container> <Grid item width={{ xs: '100%', sm: '80%', md: '35%' }} pl={{ xs: 0, md: '2.5%' }} mt={{ xs: 60, sm: 0 }}> <Grid container direction="column" alignItems={{ xs: "flex-start", sm: "flex-end" }}> <Grid item mt={{ xs: 0, md: '10vh' }} id="acum"> <Typography variant="h5" textAlign={{ xs: "left", sm: "right" }} ref={addToRevealRefs} className='gs_reveal_fromRight'> NOW WE ARE IN </Typography> </Grid> <Grid item> <Typography variant="h6" textAlign={{ xs: "left", sm: "right" }} ref={addToRevealRefs} className='gs_reveal_fromRight'> LOCATION </Typography> </Grid> <Grid item mt="10vh" id="hi"> <Typography variant="h5" textAlign={{ xs: "left", sm: "right" }} ref={addToRevealRefs} className='gs_reveal_fromRight'> SAY HI </Typography> </Grid> <Grid item className='toughts'> <Typography variant="h6" textAlign={{ xs: "left", sm: "right" }} ref={addToRevealRefs} className='gs_reveal_fromRight'> TELL US YOUR THOUGHTS </Typography> </Grid> </Grid> </Grid> </Grid> } HTML is longer and crowded, I left a part to get the idea of the structure and styling approach (MUI's sx - emotion). And finally, this is the animateReveal function: gs_reveal.js import ScrollTrigger from 'gsap/ScrollTrigger'; import gsap from 'gsap'; export default function animateReveal(elements) { const triggers = [] elements.forEach(function (elem) { hide(elem) let tr = ScrollTrigger.create({ trigger: elem, id: elem.id, end: 'bottom top', markers: true, onEnter: function () { animateFrom(elem) }, onEnterBack: function () { animateFrom(elem, -1) }, onLeave: function () { hide(elem) } }); triggers.push(tr) }); return triggers; } function animateFrom(elem, direction) { direction = direction || 1; let x = 0, y = direction * 100; if (elem.classList.contains("gs_reveal_fromLeft")) { x = -100; y = 0; } else if (elem.classList.contains("gs_reveal_fromRight")) { x = 100; y = 0; } else if (elem.classList.contains("gs_reveal_fromBelow")) { y = -100 } elem.style.transform = "translate(" + x + "px, " + y + "px)"; elem.style.opacity = "0"; gsap.fromTo(elem, { x: x, y: y, autoAlpha: 0 }, { duration: 1.25, x: 0, y: 0, autoAlpha: 1, ease: "expo", overwrite: "auto", delay: elem.classList.contains("gs_delay") ? 0.3 : 0, }); } function hide(elem) { gsap.set(elem, { autoAlpha: 0 }); } The ScrollTrigger markers are misplaced when page loads, and might move (get more misplaced) on hard reloading page, depending on the current scroll position in the moment of reloading, even though the scroll position is not preserved on reload (always is scrolled on top). - The markers are placed on the correct position on resizing, as expected. I followed gsap official docs on react and react-advanced and tried: grabbing the html elements to animate on scroll inside animateReveal() by let elements = gsap.utils.toArray(".gs_reveal"); Assigning to each element a useRef() and use the .current value for each in animateReveal() grabbing html elements using gsap's selector utility gsap.utils.selector changing to simpler animation on scroll, like just a fade refreshing ScrollTrigger in different moments useLayoutEffect(() => { ScrollTrigger.refresh(true) // or ScrollTrigger.refresh() ... }, []); 6. Lifting ScrollTrigger logic to parent about.js page 7. Assigning scrollTrigger to a timeline triggered by the to-be-reveal element 8. Use useEffect() instead of useLayoutEffect() (recommended anyway for ScrollTrigger) 7. Other who-knows-what unsuccessful twists. I suspected a rehydration error, when the static generated code does not match the client side one. But the only JS that could cause a mismatch is the gsap related one, and it does not seem an SSR issue. I checked if the CSS and HTML elements are being properly SSR-ed, by preventing JS from running in the browser. All looking fine. This is both a SSR issue (gatsby build) and a development issue (no SSR). As i said on point 5, setting a ScrollTrigger.refresh() when component is mounted does not work, but delaying this with a 1-2 seconds in a setTimeout successfully solves the issue useLayoutEffect(() => { setTimeout(() => { ScrollTrigger.refresh(true) }, 2000); }, []); This is hard to be accepted as a solution, since i cannot rely on a fixed value to 'guess' when DOM is properly rendered in the eyes of the ScrollTrigger, not to mention the glitches that might occur. So, the question is 'WHY?', why animating with ScrollTrigger from within useLayoutEffect, which is not triggered on the server anyway and should mark the 'component is successfully mounted' moment, seems to not wait for the DOM being completely painted, even though nothing is generated dynamically! There are quite of threads on this forum regarding gatsby, and none seemed to have a clear cause-outcome-solution. Is this battle lost, should i move on? Do you have any suggestions? Thanks so much for your time reading this, it means so much to me!
  11. @OSUblake for the case of Angular, I have the refresh in the OnInit hook method. This is just after registering the plugins and before using the scrollTo plugin. A brief below. ngOnInit() { gsap.registerPlugin(ScrollTrigger); gsap.registerPlugin(ScrollToPlugin); ScrollTrigger.refresh(); // refresh here ... gsap.to(window, { scrollTo: { y: this.triggers[i].trigger, autoKill: false }, overwrite: true, duration: 1, ease: 'expo.out' ... }); } I am guessing the ScrollTrigger.refresh() worked for my case because the elements used with the scroll plugin are the triggers on my ScrollTrigger config. For context, It is for the implementation I was assisted with here:
  12. Hi all, I cannot find what is causing my GSAP in Safari is buggy , laggy, choppy... well what else word can I describe haha. One of the forum links itself looks laggy in Safari. I attached the mp4 video file: left - chrome, right - safari. Here is my GSAP code for reference: function animateFrom(elem, direction) { direction = elem.getAttribute("data-reveal-direction") ?? 0.2; const delay = elem.getAttribute("data-reveal-delay") ?? 0; let x = 0, y = direction * 100; if (elem.classList.contains("js-reveal_fromLeft")) { x = -100; y = 0; } else if (elem.classList.contains("js-reveal_fromRight")) { x = 100; y = 0; } console.log("x: ", x); console.log("y: ", y); // gsap.set(elem, { x: x, y: y, autoAlpha: 0 }); elem.style.transform = "translate(" + x + "px, " + y + "px)"; elem.style.opacity = "0"; const tl = gsap.timeline({ scrollTrigger: { trigger: elem, once: true, markers: true, }, }); tl.to(elem, { duration: 1.25, x: 0, y: 0, autoAlpha: 1, ease: "power2.out", // overwrite: "auto", delay: delay, }); } function hide(elem) { gsap.set(elem, { autoAlpha: 0 }); } // Scroll reveal gsap.utils.toArray(".js-reveal").forEach(function (elem) { animateFrom(elem); }); gsap-safari-laggy.mp4
  13. Just one quick [untested] idea: liveSnap: {x: (value) => { // animate to the snapped value gsap.to(target, {x: gsap.utils.snap(100, value), duration: 0.3, overwrite: true}); // but return the unsnapped value return value; }},
  14. tldr. it feels that possibly timelines due to their nature of taking in element values straight away (not at the time of playing), might be the cause of glitch because values are constantly changing especially that its 3 timelines controlling elements. I am trying with overwrite both auto and true, but it's not working correctly. There are two problems in which focusing on the second is more important. The first one is the issue of inputing, in this case hovering, as Blake mentioned. There are methods to solve this, one being what Blake suggested. The result should strive to avoid triggering, hovering on/off , in a consecutive way. Here especially as hovering off reverses() the timeline. The second is really the overwriting issue. What seems a viable solution to me possibly presents a cornerstone mechanics for interactive control of multiple elements. On each hover, a timeline is created with .to(). At that moment timeline renders and picks up the current values in order to create the interpolation. And it starts interpolating. On a new hover, the same thing is repeated, the then-active timeline is paused/killed, and a new one is taking over. This seems plausible. In terms of Promise.All, it seems to me that it is better suited for chaining timelines/animations. Here it is taking over method, for multiple elements at the same time. Is this possibly not well suited for GSAP timelines? I pondered possibly trying to do this with JS/classes/CSS/transition. A bigger overkill would be canvas I presume.
  15. If you're animating the same properties in different timelines you can use overwrite:true Possibly even https://greensock.com/docs/v3/GSAP/Timeline/invalidate() Scaling/moving on hover is always a tricky one though because inevitably you'll find a spot whilst hovering where the element will get 'stuck' scaling up and down and in and out of your mouse 'hit area' Blake will be able to advise more on the react side of things.
  16. Hi, I would like to reset the scroll position before navigating away from a page. ScrollPlugin seems to remember the position from the previous page when on a new page. I have a sample usage: gsap.to(window, { scrollTo: { y: this.triggers[i].trigger, autoKill: false }, overwrite: true, duration: 1, ease: 'expo.out' });
  17. Hi all, In the CodePen I've set up a basic toggle that opens and closes a div. As part of the animation, the padding also expands from 0px to 20px. The 20px is however currently hard coded. What's the best way to store the divs original padding and refer to this for future animations? As currently if for example the button is toggled before the animation completes, the padding would return for example 10px if it wasn't hard coded. I was wondering if gsap had any way to store such properties? Or just storing it in a data attribute on the div is a fine solution.
  18. Well, CodePen has been down for a while so I can't provide a forked demo but here's how I'd do the JS: let n = 15; let parallax = []; // we'll store the animations in here. let clamp = gsap.utils.clamp(0, 1); let currentX = 0; let snap = gsap.utils.pipe(gsap.utils.snap(450), gsap.utils.clamp(n * -450, 0)); // Set #slides width for draggable bounds gsap.set('#slides', {width:n*450}); // Populate slide boxes for (var i=0; i<n; i++){ var box = document.createElement('div'), img = new Image(), link = document.createElement('a'); gsap.set(box, { width:400, height:600, overflow:'hidden', position:'absolute', top:50, left:i*450, attr:{ class:'box b'+i }, background:'#333' }); gsap.set(img, { position:'absolute', left:-300,//-i*50, attr:{src:'https://picsum.photos/id/'+(i+10)+'/700/600/'} }); parallax[i] = gsap.to(img, {x: 300, ease: "none", paused: true}); gsap.set(link, { position:'absolute', textAlign:'center', width:105, height:70, paddingTop:'7px', top:490, left:-25, rotation:90, fontSize:'45px', color:'#000', background:'#fff', mixBlendMode:'lighten', textDecoration:'none', innerHTML:'<span style="font-size:20px">IMG </span>'+(i+1), attr:{ class:'imgLink', href:'https://picsum.photos/id/'+(i+10)+'/700/600/', target:'_blank' }, }); box.appendChild(img); box.appendChild(link); slides.appendChild(box); } // Make #slides draggable Draggable.create('#slides', { type:'x', bounds: {left: innerWidth/2, width:1}, zIndexBoost: false, onDrag:updateParallax, inertia: true, onRelease: function() { currentX = this.endX }, onThrowUpdate: updateParallax, snap: snap }) function updateParallax() { // parallax should start from the right edge of the screen and we know that the #slides starts with its left edge centered, thus we add innerWidth/2 let x = gsap.getProperty('#slides', 'x') + window.innerWidth / 2, // convert the position in the viewport (right edge of viewport to -400 because that's when the right edge of the element would go off-screen to the left) into a progress value where it's 0 at the right edge and 1 when it reaches the left edge normalize = gsap.utils.mapRange(window.innerWidth, -400, 0, 1); // apply the clamped value to each animation parallax.forEach((animation, i) => animation.progress(clamp(normalize(x + i * 450)))); } updateParallax(); // Update draggable bounds onResize window.addEventListener('resize', ()=>{ Draggable.get("#slides").applyBounds({left: innerWidth/2, width:1}) }); // Previous & next buttons $('#prev, #next').on('click', function(e) { let nextX = snap(currentX + (e.currentTarget.id === "next" ? -450 : 450)); if (nextX !== currentX) { gsap.to("#slides", {x: nextX, duration: 0.3, onUpdate: updateParallax, overwrite: true}) currentX = nextX; } }); $('#prev, #next').on('mouseenter', (e)=>{ gsap.to('#'+e.currentTarget.id + ' circle', {attr:{r:22}, ease:'expo', overwrite: true}) }); $('#prev, #next').on('mouseleave', (e)=>{ gsap.to('#'+e.currentTarget.id + ' circle', {attr:{r:20}, ease:'expo', overwrite: true}) }); // Img Link rollover/out behavior $('.imgLink').on('mouseenter', (e)=>{ gsap.to(e.currentTarget, {x:10, duration:0.3, ease:'power3', overwrite: true}) }); $('.imgLink').on('mouseleave', (e)=>{ gsap.to(e.currentTarget, {x:0, duration:0.3, ease:'power4.inOut', overwrite: true}) }); The general idea is: You only want the parallax effect to exist while each individual element is inside the viewport (not the entire movement of the #slides). I created a simple linear animation of x from 0 to 300 for EACH element. Paused. Dumped them into an Array. The updateParallax() function loops through each one and sets the progress() according to its position (which we know because they're 450px apart). It's all based on the viewport so that progress would be 0 when it's on the far right edge of the screen and 1 when the element's right edge reaches the left edge of the viewport. I also made the following improvements: I applied inertia with snapping directly on the draggable so it's super smooth and users can flick it. The logic in the next/previous buttons allows users to click the buttons quickly and it still works (instead of ignoring clicks while animation is running). Sorry, that's my pet peeve when the interface ignores user clicks. I hope that helps, Tom!
  19. Welcome to the forums, @inkorporation I read your question a few times and I'm sorry but I don't understand what you're asking. Can you please try to explain? What exactly isn't "fluid"? I didn't see any jerky animation. But I did see very pixelated letters on some devices because you're scaling up so much. Also, do NOT enable scroll-behavior: smooth in your CSS because it interferes with ScrollTrigger functionality. I would also recommend setting overwrite: true because if you scroll quickly back and forth, you may be creating conflicting tweens since you're doing them dynamically inside the onEnter. expoScale() won't work if you don't load the EasePack, just so you know. That's one of the few eases that aren't in the core. Lastly, I don't see why you're doing y: "0%" - you never animate y to any other value, right? And if your goal is to use percentage-based "y" values, it's typically best to use yPercent instead of y so that you can layer them properly. I suspect you might be better off creating ONE timeline that contains all the [staggered] animations and just hook that one timeline up to one ScrollTrigger with scrub: true (or a number).
  20. 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.
  21. I was looking at this reference link here: // Set overwrite on a tween gsap.to(".line", { x: 200, overwrite: true }); // Set overwrite globally for all tweens gsap.defaults({ overwrite: true }); // Set overwrite for all tweens in a timeline const tl = gsap.timeline({ defaults: { overwrite: true } }); Maybe I need to set the overwrite in a difference place than a the begining of the tween. Basically seems like the timelines are conflicting each other, and not terminating the movements of the previous timeline. There are other problems , but it is better to keep them in a separate thread.
  22. Looks to me, like what you are actually doing with that tween is to tween him to his final position on the y-axis again, which is below/outside of that section and since you have overwrite set to true that will overwrite any other tweens on that parachute-guy, thus he won't be visible anymore after that. Since you have a scrub set, the timeline will play in reverse anyway when scrolling back up, so I do not see a real necessity for that tween. Some sidenotes: the toggleActions you have in that same scrollTrigger does not do anything. toggleActions and scrub are exclusive properties, they don't work alongside each other. When you have both set, the scrub will always be the one taking control of your scroll-animations for that ScrollTrigger. ScrollTriggers do not have a duration property. The duration - i.e. the amount of scroll - is being defined by the start and end of a ScrollTrigger. So maybe what you meant instead of duration: "150%" is end: "+=150%" ? let parachute = new TimelineMax({ ... }) is old syntax. I would suggest using the newer GSAP3 syntax for timelines: let parachute = gsap.timeline({ ... })
  23. I read your question a few times and I'm lost. Sorry You'll significantly improve your chances of getting a good answer if you isolate things as much as possible in a minimal demo. You shouldn't need 100 lines of JS just to show the challenge you're struggling with. Just a couple of <div> elements and a timeline or two with minimal tweens is ideal, just to show the concept. Strip out everything you possibly can. You also might want to look at this (although since I don't understand your question it may not be relevant here): By the way, there's no such thing as overwrite: true on a timeline. That's a tween special property. You can set defaults on a timeline, though, that get passed to all the child tweens. gsap.timeline({defaults: {overwrite: "auto", ease: "none"}}) That can save you some typing.
  24. Saaaay.... Is there a way to tied the timeline to the START and the END of the first tween? If I use the fromTo method it seems as if cylrod jumps to the from position regardless of where he might be located. If I use the the to method and cylrod starts from a ramdon position, then the rest of tweens fall behind thinking cylrod is always starting from the begining. The "<" is good the start motions in relation to the first tween... but it doesn't do anything to tell the rest of the tweens that the first tween already reached his finished point.. var extend = gsap.timeline({paused: true, overwrite:true}); extend.fromTo(cylrod, {x:0, duration:5, ease: "none"}, {x:200, duration:5, ease: "none"}); extend.to(pline1, {opacity:0, ease: "none"}, "<"); extend.to(rvarrow, {y:0, duration: 0.1, ease: "none"}, "<"); extend.to(sola, {opacity:1, ease: "none"}, "<"); extend.to(aline1, {opacity:1, ease: "none"}, "<"); extend.to(aline2, {opacity:0, ease: "none"}, "<"); extend.to(aline1, {opacity:0, ease: "none"}, "+=0.1"); extend.to(rvarrow, {y:-14, duration: 0.1, ease: "none"}, "<"); extend.to(aline2, {opacity:1, ease: "none"}, "<"); extend.to(sola, {opacity:0, ease: "none"}, "+=1"); extend.to(aline2, {opacity:0, ease: "none"}, "<"); extend.to (pline1, {opacity:1}, "<"); extend.to (bline1, {opacity:0}, "-=5"); extend.to (bline2, {opacity:0}, "-=5"); extend.to (solb, {opacity:0}, "-=5"); https://codepen.io/Elindo586/pen/xxrbWyY
  25. Do I need to wrap them in some sort of brackets? If so, how do I do that? The timing and sequence for each timeline is now exactly how I wanted it. I added overwrite:true for each timeline, so it would kill any conflicts with other timelines. and I added .kill() for each button so it would kill the other buttons. var start = gsap.timeline ({paused:true, overwrite: true}); btnstop.onclick = () => stop.play(); extend.kill retract.kill The problem is that the buttons and timelines are not killing the actions of previous timelines, even after I added specific details to do this job.. ALSO, for some reason the timelines are working only once per each loading of the page...