Jump to content
Search Community

Search the Community

Showing results for 'overwrite'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

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

Product Groups

  • Club GreenSock
  • TransformManager
  • Supercharge

Categories

There are no results to display.


Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Personal Website


Twitter


CodePen


Company Website


Location


Interests

Found 1,403 results

  1. @Rodrigo I have this , but in console i have this error: Uncaught ReferenceError: Draggable is not defined Isn't free ? gsap.registerPlugin(Draggable, InertiaPlugin); function horizontalLoop(items, config) { items = gsap.utils.toArray(items); config = config || {}; let tl = gsap.timeline({ repeat: config.repeat, paused: config.paused, defaults: { ease: "none" }, onReverseComplete: () => tl.totalTime(tl.rawTime() + tl.duration() * 100) }), length = items.length, startX = items[0].offsetLeft, times = [], widths = [], xPercents = [], curIndex = 0, pixelsPerSecond = (config.speed || 1) * 100, snap = config.snap === false ? (v) => v : gsap.utils.snap(config.snap || 1), // some browsers shift by a pixel to accommodate flex layouts, so for example if width is 20% the first element's width might be 242px, and the next 243px, alternating back and forth. So we snap to 5 percentage points to make things look more natural populateWidths = () => items.forEach((el, i) => { widths[i] = parseFloat(gsap.getProperty(el, "width", "px")); xPercents[i] = snap( (parseFloat(gsap.getProperty(el, "x", "px")) / widths[i]) * 100 + gsap.getProperty(el, "xPercent") ); }), getTotalWidth = () => items[length - 1].offsetLeft + (xPercents[length - 1] / 100) * widths[length - 1] - startX + items[length - 1].offsetWidth * gsap.getProperty(items[length - 1], "scaleX") + (parseFloat(config.paddingRight) || 0), totalWidth, curX, distanceToStart, distanceToLoop, item, i; populateWidths(); gsap.set(items, { // convert "x" to "xPercent" to make things responsive, and populate the widths/xPercents Arrays to make lookups faster. xPercent: (i) => xPercents[i] }); gsap.set(items, { x: 0 }); totalWidth = getTotalWidth(); for (i = 0; i < length; i++) { item = items[i]; curX = (xPercents[i] / 100) * widths[i]; distanceToStart = item.offsetLeft + curX - startX; distanceToLoop = distanceToStart + widths[i] * gsap.getProperty(item, "scaleX"); tl.to( item, { xPercent: snap(((curX - distanceToLoop) / widths[i]) * 100), duration: distanceToLoop / pixelsPerSecond }, 0 ) .fromTo( item, { xPercent: snap( ((curX - distanceToLoop + totalWidth) / widths[i]) * 100 ) }, { xPercent: xPercents[i], duration: (curX - distanceToLoop + totalWidth - curX) / pixelsPerSecond, immediateRender: false }, distanceToLoop / pixelsPerSecond ) .add("label" + i, distanceToStart / pixelsPerSecond); times[i] = distanceToStart / pixelsPerSecond; } function toIndex(index, vars) { vars = vars || {}; Math.abs(index - curIndex) > length / 2 && (index += index > curIndex ? -length : length); // always go in the shortest direction let newIndex = gsap.utils.wrap(0, length, index), time = times[newIndex]; if (time > tl.time() !== index > curIndex) { // if we're wrapping the timeline's playhead, make the proper adjustments vars.modifiers = { time: gsap.utils.wrap(0, tl.duration()) }; time += tl.duration() * (index > curIndex ? 1 : -1); } curIndex = newIndex; vars.overwrite = true; return tl.tweenTo(time, vars); } tl.next = (vars) => toIndex(curIndex + 1, vars); tl.previous = (vars) => toIndex(curIndex - 1, vars); tl.current = () => curIndex; tl.toIndex = (index, vars) => toIndex(index, vars); tl.updateIndex = () => (curIndex = Math.round(tl.progress() * (items.length - 1))); tl.times = times; tl.progress(1, true).progress(0, true); // pre-render for performance if (config.reversed) { tl.vars.onReverseComplete(); tl.reverse(); } if (config.draggable && typeof Draggable === "function") { let proxy = document.createElement("div"), wrap = gsap.utils.wrap(0, 1), ratio, startProgress, draggable, dragSnap, roundFactor, align = () => tl.progress( wrap( startProgress + (draggable.startX - draggable.x) * ratio ) ), syncIndex = () => tl.updateIndex(); typeof InertiaPlugin === "undefined" && console.warn( "InertiaPlugin required for momentum-based scrolling and snapping. https://greensock.com/club" ); draggable = Draggable.create(proxy, { trigger: items[0].parentNode, type: "x", onPress() { startProgress = tl.progress(); tl.progress(0); populateWidths(); totalWidth = getTotalWidth(); ratio = 1 / totalWidth; dragSnap = totalWidth / items.length; roundFactor = Math.pow( 10, ((dragSnap + "").split(".")[1] || "").length ); tl.progress(startProgress); }, onDrag: align, onThrowUpdate: align, inertia: true, snap: (value) => { let n = Math.round(parseFloat(value) / dragSnap) * dragSnap * roundFactor; return (n - (n % 1)) / roundFactor; }, onRelease: syncIndex, onThrowComplete: () => gsap.set(proxy, { x: 0 }) && syncIndex() })[0]; } return tl; }
  2. Hi, Maybe a different logic for every element that is not the first, instead of selecting the ScrollTrigger for the current element and using that start point, use the previous ScrollTrigger (if any) end point: const menuLinks = gsap.utils.toArray("header ul li button"); menuLinks.forEach((elem, i) => { elem.addEventListener("click", function () { let target = elem.getAttribute("data-panel"), trigger = ScrollTrigger.getById(target); if (i > 0) { target = menuLinks[i - 1].getAttribute("data-panel"); trigger = ScrollTrigger.getById(target); } gsap.to(window, { duration: 1, scrollTo: i > 0 ? trigger.end : trigger.start, overwrite: true }); }); }); Hopefully this helps. Happy Tweening!
  3. Hi @LVegetable welcome to the forum! Have you seen our Stackblitz starter templates? It has a boilerplate for all the major frameworks, including next.js In all my time developing websites I've never needed to overwrite the default scroll behaviour there is always a better way, I think. From your description I would also not read anything that needs to overwrite the default scroll behaviour. Your background can just be a fixed element and the other elements can just scroll or animate them with the y property in GSAP. Keep in mind that everything in GSAP is an animation, even things on scroll start out as an animation. Check out this tutorial how to work with ScrollTrigger Personally I always start in codepen and really focus on the logic I need before I bring it over to my framework. It usually takes me around 10 versions to get to a state I am happy with and then it will be trivial to port it over to what ever framework you like, but the web is basic HTML, CSS, JS so if that is solid it will work any where! You can work with React in codepen and you can then set it up like the pen below. But again, personally I would remove all abstractions and just focus on the basics and when that is working your can port it to what ever you like. Hope it helps and happy tweening! https://codepen.io/GreenSock/pen/OJmQvLZ?editors=0010
  4. Hello, I was not able to recreate this issue in codesandbox or stackblitz, but hope you can give some insight based on what I can provide here. I have a Next.js website using the pages router, and I have an issue with a component that has elements rendered dynamically from a script after the component mounts. (It's a social media feed from Curator.io) The posts in the feed have a scrolltrigger applied to them after the feed has loaded. const curatorContainer = useRef() useGSAP(() => { if ( feedLoaded ) { ScrollTrigger.create({ trigger: curatorContainer.current, start: "top bottom-=200px", onEnter: () => { gsap.fromTo('.crt-post-c', { opacity: 0 }, { opacity: 1, duration: 0.75, delay: 0.2, stagger: 0.1, overwrite: 'auto' }) }, onLeaveBack: () => { gsap.to('.crt-post-c', { opacity: 0, duration: 0.5, overwrite: 'auto' }) }, }) } }, { scope: curatorContainer, dependencies: [feedLoaded] }) return ( <div ref={curatorContainer}> ... </div> ) On the first load everything works fine, but if I navigate to another page and back to the page with this component, I get several "Invalid scope" errors in the console (some on a gsap timeline unrelated to the component that seems to cause the errors). I also get the error "GSAP target .crt-post-c not found." even tho this code spicifically checks for any existing .crt-post-c before running. However the animations work without issues, so I just want to know what's causing the errors and if I can get rid of them. There is no errors when using this same gsap implementation on things that aren't dynamically rendered.
  5. Hello! I just faced a problem where overwrite: 'auto', is not overwriting pending staggered items. In the codepen, you can easily reproduce by clicking the show button and then quickly the hide button (while the "show" timeline is still animating), or by pressing the simulate button (which show then hide quickly). The issue is that the elements currently showing using a stagger, are not going to be "overwrited" by the hiding timeline that is not using any stagger. I guess that's because the overwrite: 'auto' of the "show" will be applied when the staggered items start animating, so it will overwrite the tween applied in the "hide". I I believe that this should not behave like that, but maybe I am wrong and this is the expected behaviour. Waiting for your answer! Thanks !
  6. hi, i have issue with promise, is there any way to resolve `await Promise.all([ tl1 ])` when we overwrite a instance properties ? Some of my promise wait for animations but never resolve because they get crush somewhere in another child actions. ```ts gsap.defaults({ overwrite: 'auto', onInterrupt:function() { this.progress( 1 ); // force progress 100%, kill la promise pour les async await. } }); // test gsap promise all setTimeout( async () => { console.log( '💚' ); const obj = { x:0 }; const tl1 = gsap.timeline().to( obj, { x:8 }); const tl2 = gsap.timeline().to( obj, { x:5 }); // comment me for resolve Promise.all setTimeout( async () => { await tl1; console.log( '💚1' ); await Promise.all([ tl1 ]); console.log( '💚2' ); // never fired if tl2 executed }, 10 ); }, 1000 ); ``` is a `onInterrupt` bug ? or maybe we have another global cb for handle those case ? thanks
  7. Hello everyone, I'm currently trying to replicate the effect demonstrated in the uploaded GIF. While I've successfully implemented the easing effect, I'm encountering difficulties with the stagger effect. I've experimented with various approaches, with the latest attempt shown below. I can prepare a CodePen example if needed. Perhaps I'm overlooking something simple. Any guidance or suggestions would be greatly appreciated. Thank you! useGSAP(() => { let proxy = { translate: 0 }, translateSetter = gsap.quickSetter(".video-grid-content-container", "translateY", "px"), clamp = gsap.utils.clamp(-40, 40); ScrollTrigger.create({ onUpdate: (self) => { let translate = clamp(self.getVelocity() / -100); if (Math.abs(translate) > Math.abs(proxy.translate)) { proxy.translate = translate; gsap.to(proxy, { translate: 0, duration: 0.4, stagger: { amount: 10, from: "start" }, overwrite: true, onUpdate: () => translateSetter(proxy.translate) }); } } }); });
  8. Hi, The first issue in your code is that you're using the quick setter on the parent element, that is the element that contains the grid, and not the grid elements so staggering will have no effect whatsoever. Then I fail to see the point of a quick setter if you can achieve the same with just a GSAP Tween that gets overwritten if another is created. Something like this: useGSAP(() => { let proxy = { translate: 0 }, translateSetter = gsap.quickSetter('.video-container', 'y', 'px'), clamp = gsap.utils.clamp(-1000, 1000); ScrollTrigger.create({ onUpdate: (self) => { translateSetter(clamp(self.getVelocity() / -100)); gsap.to('.video-container', { y: 0, duration: 0.2, stagger: 0.05, overwrite: true, }); }, }); }); Here is a fork of your demo with that approach: https://stackblitz.com/edit/react-hnfbhc?file=src%2FApp.js Hopefully this helps. Happy Tweening!
  9. Man, this seemed extremely simple of a request in my head... but things like this never are simple, are they? Good question, I mean the specifics of how this will function can be planned later on when you guys decide to implement this... but if I had to chime in now on this specific scenario, I'd say there are more than one option: 1) This will do nothing. Because a motionPath in the context of a FLIP, serves only to overwrite an existing animation... so if a Y animation isn't part of the FLIP, then the motionPath will do nothing. OR 2) If it's used in the same way I used my motionPath, it adds a little detour/curve, but the starting point and ending point is still the same. And I love that about FLIP. To give a helpful analogy like @Rodrigo did earlier, I love the fact that I can just let FLIP take the wheel and take me to my destination. But that doesn't mean I don't want to, as the passenger, ask FLIP to sometimes take a different path than the one it chooses long as the path leads to the same destination. I hope this clarifies my request/idea.
  10. Ah, that's because inside the helper function there was a "resize" event handler that was re-initiating things. I just edited the helper function to put it inside a gsap.context() that uses a cleanup function for the "resize" event handler to remove that: https://stackblitz.com/edit/stackblitz-starters-jbsvf4?file=app%2Fhelper.js function horizontalLoop(items, config) { let timeline; items = gsap.utils.toArray(items); config = config || {}; gsap.context(() => { // use a context so that if this is called from within another context or a gsap.matchMedia(), we can perform proper cleanup like the "resize" event handler on the window let onChange = config.onChange, lastIndex = 0, tl = gsap.timeline({repeat: config.repeat, onUpdate: onChange && function() { let i = tl.closestIndex(); if (lastIndex !== i) { lastIndex = i; onChange(items[i], i); } }, paused: config.paused, defaults: {ease: "none"}, onReverseComplete: () => tl.totalTime(tl.rawTime() + tl.duration() * 100)}), length = items.length, startX = items[0].offsetLeft, times = [], widths = [], spaceBefore = [], xPercents = [], curIndex = 0, indexIsDirty = false, center = config.center, pixelsPerSecond = (config.speed || 1) * 100, snap = config.snap === false ? v => v : gsap.utils.snap(config.snap || 1), // some browsers shift by a pixel to accommodate flex layouts, so for example if width is 20% the first element's width might be 242px, and the next 243px, alternating back and forth. So we snap to 5 percentage points to make things look more natural timeOffset = 0, container = center === true ? items[0].parentNode : gsap.utils.toArray(center)[0] || items[0].parentNode, totalWidth, getTotalWidth = () => items[length-1].offsetLeft + xPercents[length-1] / 100 * widths[length-1] - startX + spaceBefore[0] + items[length-1].offsetWidth * gsap.getProperty(items[length-1], "scaleX") + (parseFloat(config.paddingRight) || 0), populateWidths = () => { let b1 = container.getBoundingClientRect(), b2; items.forEach((el, i) => { widths[i] = parseFloat(gsap.getProperty(el, "width", "px")); xPercents[i] = snap(parseFloat(gsap.getProperty(el, "x", "px")) / widths[i] * 100 + gsap.getProperty(el, "xPercent")); b2 = el.getBoundingClientRect(); spaceBefore[i] = b2.left - (i ? b1.right : b1.left); b1 = b2; }); gsap.set(items, { // convert "x" to "xPercent" to make things responsive, and populate the widths/xPercents Arrays to make lookups faster. xPercent: i => xPercents[i] }); totalWidth = getTotalWidth(); }, timeWrap, populateOffsets = () => { timeOffset = center ? tl.duration() * (container.offsetWidth / 2) / totalWidth : 0; center && times.forEach((t, i) => { times[i] = timeWrap(tl.labels["label" + i] + tl.duration() * widths[i] / 2 / totalWidth - timeOffset); }); }, getClosest = (values, value, wrap) => { let i = values.length, closest = 1e10, index = 0, d; while (i--) { d = Math.abs(values[i] - value); if (d > wrap / 2) { d = wrap - d; } if (d < closest) { closest = d; index = i; } } return index; }, populateTimeline = () => { let i, item, curX, distanceToStart, distanceToLoop; tl.clear(); for (i = 0; i < length; i++) { item = items[i]; curX = xPercents[i] / 100 * widths[i]; distanceToStart = item.offsetLeft + curX - startX + spaceBefore[0]; distanceToLoop = distanceToStart + widths[i] * gsap.getProperty(item, "scaleX"); tl.to(item, {xPercent: snap((curX - distanceToLoop) / widths[i] * 100), duration: distanceToLoop / pixelsPerSecond}, 0) .fromTo(item, {xPercent: snap((curX - distanceToLoop + totalWidth) / widths[i] * 100)}, {xPercent: xPercents[i], duration: (curX - distanceToLoop + totalWidth - curX) / pixelsPerSecond, immediateRender: false}, distanceToLoop / pixelsPerSecond) .add("label" + i, distanceToStart / pixelsPerSecond); times[i] = distanceToStart / pixelsPerSecond; } timeWrap = gsap.utils.wrap(0, tl.duration()); }, refresh = (deep) => { let progress = tl.progress(); tl.progress(0, true); populateWidths(); deep && populateTimeline(); populateOffsets(); deep && tl.draggable ? tl.time(times[curIndex], true) : tl.progress(progress, true); }, onResize = () => refresh(true), proxy; gsap.set(items, {x: 0}); populateWidths(); populateTimeline(); populateOffsets(); window.addEventListener("resize", onResize); function toIndex(index, vars) { vars = vars || {}; (Math.abs(index - curIndex) > length / 2) && (index += index > curIndex ? -length : length); // always go in the shortest direction let newIndex = gsap.utils.wrap(0, length, index), time = times[newIndex]; if (time > tl.time() !== index > curIndex && index !== curIndex) { // if we're wrapping the timeline's playhead, make the proper adjustments time += tl.duration() * (index > curIndex ? 1 : -1); } if (time < 0 || time > tl.duration()) { vars.modifiers = {time: timeWrap}; } curIndex = newIndex; vars.overwrite = true; gsap.killTweensOf(proxy); return vars.duration === 0 ? tl.time(timeWrap(time)) : tl.tweenTo(time, vars); } tl.toIndex = (index, vars) => toIndex(index, vars); tl.closestIndex = setCurrent => { let index = getClosest(times, tl.time(), tl.duration()); if (setCurrent) { curIndex = index; indexIsDirty = false; } return index; }; tl.current = () => indexIsDirty ? tl.closestIndex(true) : curIndex; tl.next = vars => toIndex(tl.current()+1, vars); tl.previous = vars => toIndex(tl.current()-1, vars); tl.times = times; tl.progress(1, true).progress(0, true); // pre-render for performance if (config.reversed) { tl.vars.onReverseComplete(); tl.reverse(); } if (config.draggable && typeof(Draggable) === "function") { proxy = document.createElement("div") let wrap = gsap.utils.wrap(0, 1), ratio, startProgress, draggable, dragSnap, lastSnap, initChangeX, wasPlaying, align = () => tl.progress(wrap(startProgress + (draggable.startX - draggable.x) * ratio)), syncIndex = () => tl.closestIndex(true); typeof(InertiaPlugin) === "undefined" && console.warn("InertiaPlugin required for momentum-based scrolling and snapping. https://greensock.com/club"); draggable = Draggable.create(proxy, { trigger: items[0].parentNode, type: "x", onPressInit() { let x = this.x; gsap.killTweensOf(tl); wasPlaying = !tl.paused(); tl.pause(); startProgress = tl.progress(); refresh(); ratio = 1 / totalWidth; initChangeX = (startProgress / -ratio) - x; gsap.set(proxy, {x: startProgress / -ratio}); }, onDrag: align, onThrowUpdate: align, overshootTolerance: 0, inertia: true, snap(value) { //note: if the user presses and releases in the middle of a throw, due to the sudden correction of proxy.x in the onPressInit(), the velocity could be very large, throwing off the snap. So sense that condition and adjust for it. We also need to set overshootTolerance to 0 to prevent the inertia from causing it to shoot past and come back if (Math.abs(startProgress / -ratio - this.x) < 10) { return lastSnap + initChangeX } let time = -(value * ratio) * tl.duration(), wrappedTime = timeWrap(time), snapTime = times[getClosest(times, wrappedTime, tl.duration())], dif = snapTime - wrappedTime; Math.abs(dif) > tl.duration() / 2 && (dif += dif < 0 ? tl.duration() : -tl.duration()); lastSnap = (time + dif) / tl.duration() / -ratio; return lastSnap; }, onRelease() { syncIndex(); draggable.isThrowing && (indexIsDirty = true); }, onThrowComplete: () => { syncIndex(); wasPlaying && tl.play(); } })[0]; tl.draggable = draggable; } tl.closestIndex(true); lastIndex = curIndex; onChange && onChange(items[curIndex], curIndex); timeline = tl; return () => window.removeEventListener("resize", onResize); // cleanup }); return timeline; } Is that better?
  11. Hi @Ponnyprisma and welcome to the GSAP Forums! Sorry to hear about the problems but if you can't reproduce it on a codepen demo there is not a lot we can do about it. On top of that the demo you posted shows that this is not a GSAP related problem, but something else in your app is clearly interfering with how things are being done. There are known issues (not a lot) when using some features by Bootstrap 5, manly because it adds scroll-behavior: smooth to your body element, so if you're using Bootstrap 5 you can overwrite that in your own CSS. Sorry I can't be of more assistance. Happy Tweening!
  12. Hi there, I'm using near latest npm greensock (3.11.4), and there seems to be a change in behaviour since version 2.0.1 and I'm not sure how to resolve it. Before I could have 3 items with infinitely repeating tween inside a timeline, but later I want to stop those tweens on a delay (so they don't stop at the same time), but I don't want to pause the timeline... so I'd add my tweens to a timeline like this: ``` // start rows anim this.spinTimeline = new TimelineLite({paused:true}); _.each(this.rows, (row, i) => { var slideTween = new TweenMax(row.sprite, 3, {x: row.offset, ease: Power0.easeNone, repeat: -1 }); this.spinTimeline.add(slideTween , "startRowT" + i, "-=0.1"); }); this.spinTimeline.play(); ``` then later I could stop them animating repeatedly by just calling a new tween on the row.sprite, with a slightly increasing delay on each, and the animations would transition smoothly from repeating x to landing on a specific point on the x axis. ``` stopRows() { _.each(this.rows, (row, i) => { TweenMax.to(row.sprite, 0.75, {x: row.offset, ease: Elastic.easeOut, delay: 0.75 * i, onComplete: this.animComplete.bind(this) }); }); } ``` Now with latest gsap versions I can't figure out how to recreate this. the repeating tween just keeps playing after the stopping tween finishes. If I pause the timeline first, it works but the repeating anims pause immediately.. If I use overwrite: true, then the repeating anims pause immediately (not when the stop anim starts after the delay). If I use timeline.killTweensOf(row.sprite) onStart, then it happens immediately, (not after the delay).. so i can't transition from one tween to the other anymore. My new code looks like this: ``` // start anim const tl = this.tl; this.rows.map((row, i) => { const offsetX = row.container.width / 2; tl.to(row.container, {x: offsetX, duration: 3, ease: 'none', repeat: -1}); }); tl.play(); // stop anim: this.rows.map((row, i) => { const toX = row.stopOffset; gsap.to(row.container, { duration: 1, x: toX , ease: 'elastic.out', delay: 0.75 * i, overwrite: true, // i'd expect this overwrite to happen after the delay, not immediately. onComplete: () => { //this.tl.killTweensOf(row.container); this.state = 'ready'; }, }); }); Edit: I found the problem, I needed to remove the duration from my new version and use t.killTweensOf in the onComplete (the line i had commented!).. that works as I want now!
  13. thanks for the additional info. I believe this has to do with overwriting. You are creating conflicting tweens and my guess is that when played in reverse the animation that animates from x:0, y:0 to x:0, y:0 is winning the battle and thus you see the box jump back to the initial start state. If you set overwrite:"auto" on tweens 2 and 3 then: tween 2 will kill the y portion of tween 1 tween 3 will kill the x portion of tween 1 I think this works for this exact scenario you have https://codepen.io/snorkltv/pen/PoLZZaE?editors=0010 If you set overwrite:true then tween 3 will kill BOTH tween 1 and tween 2. You can give it a try to see how that looks (bad) from the docs https://gsap.com/docs/v3/GSAP/Tween I also think this video will help with overwrite modes I know you are saying that the tweens are automatically generated, but my advice would be to add whatever logic necessary to avoid creating conflicting tweens in the first place. Hopefully overwrite:auto solves the problem Carl
  14. Yep, it's all pure logic issues. Imagine you scroll down and then back up rather quickly. So your onLeaveBack() fires for the first card: gsap.timeline() .to(card, { duration: 1, ... }).to(card, { y: 0, duration: 0.8, overwrite: "auto" }, '-=0.2'); That means the card's "y" won't start animating for 0.8 seconds. But we keep scrolling back to where this gets triggered: gsap.to('.card', { y: 1000, duration: 1, stagger: { amount: 0.5, }, overwrite: "auto" }); So this one starts IMMEDIATELY animating that same element's y back to 1000 (this is where we want it to land at this point), and overwrite: "auto" means that it'll only find IN-PROGRESS tweens of the same property of the same element and kill those...but remember that the previous one we started would WAIT 0.8 seconds before beginning...so it hasn't started yet, thus it won't get overwritten. 0.8 seconds later, that [old] tween starts animating card.y back to 0! See the problem? You could set overwrite: true on the main staggered animation so that it immediately overwrites any tweens of that same element, regardless of if they're in-progress or not. Again, this is all just logic stuff. I hope that clears things up.
  15. Hi @benrbnt. Yes, this is definitely expected behavior. From the docs: In your demo, the animations that haven't started yet aren't "active", thus they'd be immune from the overwrite behavior. It is not intended to find all future animations that haven't even started yet and overwrite those; it's only for ACTIVE (in-progress) animations. It could be quite problematic if you've got a whole bunch of animations that do various things to a particular element in the future and then you start a tween now that has overwrite: "auto" that nukes all future tweens, even ones that haven't started or are paused or whatever. See the problem? You can simply do overwrite: true if you'd like to nuke all those instead. Or you can use gsap.killTweensOf() to target just specific properties, like gsap.killTweensOf(myObject, "opacity,y"); Does that clear things up? And thanks for being a Club GSAP member! 💚
  16. I noticed a problem with the Firefox browser. I have a looping marquee made with the seamless loop helper function and the Observer plugin on my website, it works great on every browser except Firefox. The marquee loops and it can be controlled with the scroll wheel with the help of the Observer plugin. I have hover event listeners to stop the marquee when I'm hovering on it. When the marquee stops I can scroll normally, when I hover out and the marquee resumes, the scrolling goes back to extremely slow again. This only happens on Mozilla Firefox, works great on the other browsers. Here's the code I'm using for the marquee gsap.registerPlugin(Observer); document.addEventListener("DOMContentLoaded", () => { const projectsList = document.querySelector(".horizontal_projects-wrap"); projectsList.addEventListener('pointerenter', pauseLoop); projectsList.addEventListener('pointerleave', playLoop); const names = document.querySelectorAll(".horizontal_project-title") let hovered = false; function pauseLoop () { tl.pause(); loopObserver.disable(); hovered = true; } function playLoop () { tl.play(); loopObserver.enable(); hovered = false; } const tl = horizontalLoop(names, { repeat: -1, }); const loopObserver = Observer.create({ type: 'wheel', onChangeY(self) { let factor = 2; if (self.deltaY < 0) { factor *= -1.4; } else { factor *= 1.4; } gsap.to(tl, { timeScale: factor * 2, duration: .15, }) gsap.to(tl, { timeScale: factor / 2, duration: .15, onComplete: () => { if (factor<0) { gsap.to(tl, { timeScale: 1, duration: 0.1, }) } } }, "+=.1"); } }); }); /* This helper function makes a group of elements animate along the x-axis in a seamless, responsive loop. Features: - Uses xPercent so that even if the widths change (like if the window gets resized), it should still work in most cases. - When each item animates to the left or right enough, it will loop back to the other side - Optionally pass in a config object with values like "speed" (default: 1, which travels at roughly 100 pixels per second), paused (boolean), repeat, reversed, and paddingRight. - The returned timeline will have the following methods added to it: - next() - animates to the next element using a timeline.tweenTo() which it returns. You can pass in a vars object to control duration, easing, etc. - previous() - animates to the previous element using a timeline.tweenTo() which it returns. You can pass in a vars object to control duration, easing, etc. - toIndex() - pass in a zero-based index value of the element that it should animate to, and optionally pass in a vars object to control duration, easing, etc. Always goes in the shortest direction - current() - returns the current index (if an animation is in-progress, it reflects the final index) - times - an Array of the times on the timeline where each element hits the "starting" spot. There's also a label added accordingly, so "label1" is when the 2nd element reaches the start. */ function horizontalLoop(items, config) { items = gsap.utils.toArray(items); config = config || {}; let tl = gsap.timeline({repeat: config.repeat, paused: config.paused, defaults: {ease: "none"}, onReverseComplete: () => tl.totalTime(tl.rawTime() + tl.duration() * 100)}), length = items.length, startX = items[0].offsetLeft, times = [], widths = [], xPercents = [], curIndex = 0, pixelsPerSecond = (config.speed || 1) * 100, snap = config.snap === false ? v => v : gsap.utils.snap(config.snap || 1), // some browsers shift by a pixel to accommodate flex layouts, so for example if width is 20% the first element's width might be 242px, and the next 243px, alternating back and forth. So we snap to 5 percentage points to make things look more natural totalWidth, curX, distanceToStart, distanceToLoop, item, i; gsap.set(items, { // convert "x" to "xPercent" to make things responsive, and populate the widths/xPercents Arrays to make lookups faster. xPercent: (i, el) => { let w = widths[i] = parseFloat(gsap.getProperty(el, "width", "px")); xPercents[i] = snap(parseFloat(gsap.getProperty(el, "x", "px")) / w * 100 + gsap.getProperty(el, "xPercent")); return xPercents[i]; } }); gsap.set(items, {x: 0}); totalWidth = items[length-1].offsetLeft + xPercents[length-1] / 100 * widths[length-1] - startX + items[length-1].offsetWidth * gsap.getProperty(items[length-1], "scaleX") + (parseFloat(config.paddingRight) || 0); for (i = 0; i < length; i++) { item = items[i]; curX = xPercents[i] / 100 * widths[i]; distanceToStart = item.offsetLeft + curX - startX; distanceToLoop = distanceToStart + widths[i] * gsap.getProperty(item, "scaleX"); tl.to(item, {xPercent: snap((curX - distanceToLoop) / widths[i] * 100), duration: distanceToLoop / pixelsPerSecond}, 0) .fromTo(item, {xPercent: snap((curX - distanceToLoop + totalWidth) / widths[i] * 100)}, {xPercent: xPercents[i], duration: (curX - distanceToLoop + totalWidth - curX) / pixelsPerSecond, immediateRender: false}, distanceToLoop / pixelsPerSecond) .add("label" + i, distanceToStart / pixelsPerSecond); times[i] = distanceToStart / pixelsPerSecond; } function toIndex(index, vars) { vars = vars || {}; (Math.abs(index - curIndex) > length / 2) && (index += index > curIndex ? -length : length); // always go in the shortest direction let newIndex = gsap.utils.wrap(0, length, index), time = times[newIndex]; if (time > tl.time() !== index > curIndex) { // if we're wrapping the timeline's playhead, make the proper adjustments vars.modifiers = {time: gsap.utils.wrap(0, tl.duration())}; time += tl.duration() * (index > curIndex ? 1 : -1); } curIndex = newIndex; vars.overwrite = true; return tl.tweenTo(time, vars); } tl.next = vars => toIndex(curIndex+1, vars); tl.previous = vars => toIndex(curIndex-1, vars); tl.current = () => curIndex; tl.toIndex = (index, vars) => toIndex(index, vars); tl.times = times; tl.progress(1, true).progress(0, true); // pre-render for performance if (config.reversed) { tl.vars.onReverseComplete(); tl.reverse(); } return tl; }
  17. I've tested on my Mac and I don't see what you mean, sorry. Your code seems quite inefficient to me. This is a bit better, although it could be further optimized: https://codepen.io/GreenSock/pen/xxeOjLZ?editors=1010 Make sure you overwrite previous tweens so you're not continually creating new conflicting ones that are fighting for the same property. And a modifier is better than an onUpdate for what you're doing. Are you saying that when you scroll all the way to the bottom of the page, you want your x animation to suddenly stop? Does it work the way you want if you REMOVE Lenis? That's not a GreenSock product, so we can't really support that. I think the whole point of Lenis is that it'll smooth the scroll so that it doesn't suddenly stop, so I wonder if what you're asking is more of a Lenis question, not a GSAP one(?)
  18. @Cassie @GreenSock Thanks for the reply, however I am using 2 timelines with same pin value, as I need to implement the following scenarios 1. I need to scale out the image or video from starting to its final value - Timeline 1 with same pin value. - It's working perfectly ( imageTimelineAnimation in the below code) 2. The second timeline is for snap scrolling the other images / Videos while the component is pinned. - Timeline 2 - This also works. (snapScrollAnimation in the below code) however the pinning is working and animation also plays smooth, but it's leaving large space at the bottom for desktop, tablet, mobile. I am adding margin bottom to the main container to adjust the bottom spacing. but while doing snap scrolling until I reach the last element it never appears on the screen, I have given fixed height for the container as well but not helping. I want to make the next element of the container to be maintaining the exact bottom spacing which I want to but struggling to achieve that. Need your suggestion if you know anything I'm missing. The elements I'm making animations are inside a grid container - FYI I understand that it'll be tough to understand to provide any suggestions based on the explanation on this, but whatever I know I have posted here to seek help on this. I would like to tell you that it's a really great package, you guys are Rockstars. Keep rocking. This is my code for your reference, it's huge but it gives you overall picture of what I'm trying to do ( Starting Point InitializeAnimation ) import gsap from 'gsap'; import { ScrollTrigger } from 'gsap/dist/ScrollTrigger'; export function getScrollY() { return window.pageYOffset != null ? window.pageYOffset : document.documentElement.scrollTop != null ? document.documentElement.scrollTop : document.body.scrollTop; } export function isLandscape() { return window?.matchMedia('(orientation: landscape)')?.matches; } export function detectTabletOrientation() { return isLandscape() && window.innerWidth < 1180 ? '10% 65%' : isLandscape() && window.innerWidth >= 1180 && window.innerWidth < 1400 ? '10% 80%' : '20% 50%'; } let currentCount = 0; // Text Area - START export const slidePrevNextText = (current, next) => { const currentText = gsap.fromTo( current, { autoAlpha: 1, duration: 1, overwrite: 'auto', paused: true, x: 0, }, { autoAlpha: 0, duration: 1, overwrite: 'auto', paused: true, x: '-200px', } ); const nextText = gsap.fromTo( next, { autoAlpha: 0, duration: 1, overwrite: 'auto', paused: true, x: 0, }, { autoAlpha: 1, duration: 1, overwrite: 'auto', paused: true, x: 0, } ); currentText.play('<'); nextText.play('>'); return [currentText, nextText]; }; export const slidePrevNextTextReverse = (current, next) => { const currentText = gsap.fromTo( current, { autoAlpha: 1, duration: 1, overwrite: 'auto', paused: true, x: 0, }, { autoAlpha: 0, duration: 1, overwrite: 'auto', paused: true, x: 0, } ); const nextText = gsap.fromTo( next, { autoAlpha: 0, duration: 1, overwrite: 'auto', paused: true, x: '-200px', }, { autoAlpha: 1, duration: 1, overwrite: 'auto', paused: true, x: 0, } ); currentText.play('<'); nextText.play('>'); return [currentText, nextText]; }; // Text Area - END // Initial Move out animation for Device asset and Optional Element const mainContainerTween = (id, isTablet, isMobile) => gsap.fromTo( `div#device-${id} .device-outline-border`, { duration: 2, opacity: 1, overwrite: 'auto', paused: true, stagger: 0.1, visibility: 'visible', x: 0, y: 0, yPercent: 0, }, { duration: 2, opacity: 1, overwrite: 'auto', paused: true, stagger: 0.1, visibility: 'visible', x: isTablet ? -135 : -225, y: !isTablet && !isMobile ? -50 : 0, yPercent: !isTablet ? -4 : 0, } ); const childContainerTween = (id, isTablet) => gsap.fromTo( `div#device-${id} div.child-container`, { bottom: '0', duration: 2, left: isTablet ? '9%' : '14%', opacity: 0, overwrite: 'auto', paused: true, position: 'relative', right: '0', stagger: 0.1, top: '-35%', visibility: 'hidden', x: 0, y: !isTablet ? -150 : 0, }, { bottom: '0', duration: 2, opacity: 1, overwrite: 'auto', paused: true, position: 'relative', right: '0', stagger: 0.1, visibility: 'visible', x: isTablet && window.innerWidth < 1024 ? 350 : isTablet && window.innerWidth >= 1024 ? 420 : 520, y: !isTablet ? -125 : -36, } ); const progressButtonTween = (id) => gsap.fromTo( `.progress-container--${id}`, { opacity: 0, overwrite: 'auto', paused: true, visibility: 'hidden', }, { opacity: 1, overwrite: 'auto', paused: true, visibility: 'visible', } ); const progressButtonPositionSet = (id, buttonStyles?) => gsap.set(`.progress-container--${id}`, { ...buttonStyles, }); const progressElementPosition = (id, styles) => gsap.set(`.progress-container--${id}`, { ...styles, }); const fullScreenTween = (id, isTablet?) => gsap.fromTo( `div#device-${id} .full-screen`, { duration: 0.6, opacity: 0, overflowY: isTablet ? 'hidden' : 'auto', visibility: 'hidden', }, { duration: 0.6, opacity: 1, overflowY: 'auto', visibility: 'visible', } ); const firstImageGradientTween = (id) => gsap.fromTo( `div#device-${id} div.asset-overlay`, { duration: 0.6, opacity: 1, paused: true, visibility: 'visible', }, { duration: 0.6, opacity: 0, paused: true, visibility: 'hidden', } ); export const scrollWindowToTween = (value, seconds?) => gsap.to(window, { duration: seconds ? seconds : 2.25, overwrite: 'auto', paused: true, scrollTo: { y: value, }, }); const firstTextAreaTween = (id, isMobile?, isTablet?) => gsap.fromTo( `.tarea--${id}:first-child`, { paused: true, y: 0, }, { paused: true, y: isMobile ? -10 : 0, } ); export const initialImageAnimation = (id, isTablet, isMobile) => { const dCards = gsap?.utils?.toArray(`div.asset--${id} div.asset-component`); const sCards = gsap?.utils?.toArray(`div.optional--${id}`); const [, snapTrigger] = ScrollTrigger.getAll(); return scrollWindowToTween(snapTrigger.start, 2.5) .play() .eventCallback('onStart', () => { firstImageGradientTween(id).play('<'); firstTextAreaTween(id, isMobile, isTablet).play('<'); gsap.to(`div#device-${id} div.drop-shadow`, { opacity: 1, transition: 'opacity 1s, visibility 1s', visibility: 'visible', }); }) .eventCallback('onComplete', () => { if (!isMobile) { if (secondaryCards.length > 0 && window.innerHeight > 719) { mainContainerTween(id, isTablet, isMobile).play('-=2.5'); childContainerTween(id, isTablet) .play('-=2.5') .eventCallback('onStart', () => { if (isTablet && window.innerWidth > 600 && window.innerWidth < 1024) { gsap.to(`div#device-${id} div.child-container`, { inset: window.innerWidth < 820 ? `-20% 0px 0px 2%` : `-20% 0px 0px 7%`, }); } }); } if (dCards.length > 1) { progressButtonTween(id).play('>'); } if (dCards.length >= 1) { fullScreenTween(id, isTablet).play('>'); } } }); }; export const reverseInitialImageAnimation = (id, isTablet, isMobile) => { const dCards = gsap?.utils?.toArray(`div.asset--${id} div.asset-component`); const sCards = gsap?.utils?.toArray(`div.optional--${id}`); const [imageTrigger] = ScrollTrigger.getAll(); return scrollWindowToTween(imageTrigger.start - 50, 2.5) .play() .eventCallback('onStart', () => { firstImageGradientTween(id).reverse('<'); firstTextAreaTween(id).reverse('<'); if (!isMobile) { if (sCards.length > 0) { mainContainerTween(id, isTablet, isMobile).reverse('-=1.5'); childContainerTween(id, isTablet).reverse('-=1.5'); gsap.to(`div#device-${id} div.drop-shadow`, { opacity: 0, transition: 'opacity 1s, visibility 1s', visibility: 'hidden', }); } if (dCards.length > 1) { progressButtonTween(id).reverse(0); } if (dCards.length >= 1) { fullScreenTween(id, isTablet).reverse(0); } } }); }; async function finishOnFastLeave( { isActive, progress, getVelocity, animation, direction }: ScrollTrigger, current: number, id: any ) { const dCards = gsap?.utils?.toArray(`div.parent-container div.asset--${id}`); const sCards = gsap?.utils?.toArray(`div.child-container div.optional--${id}`); const textElements = gsap?.utils?.toArray(`.tarea--${id}`); const progressValue = +progress.toPrecision(2) * 100; const length = dCards.length - 1; const index = Math.round(+(+(progressValue / 100).toPrecision(1) * length).toPrecision(1)); const currentCard: any = dCards[current]; const currentSecondaryCard: any = sCards[current]; const targetCard: any = dCards[index]; const targetSecondaryCard: any = sCards[index]; if (!isActive && Math.abs(getVelocity()) > 1000) { await animation.progress(progress === 1 ? 1 : 0).pause(); slideTween(targetCard, targetSecondaryCard) .play() .eventCallback('onStart', () => { slidePrevNextText(textElements[current], textElements[index]); const currentElements: any = textElements.filter((ele, i) => i !== index); gsap.set([...currentElements], { autoAlpha: 0, }); }) .eventCallback('onComplete', () => { slideTween(currentCard, currentSecondaryCard).reverse(); }); } } // first card Animation here export const firstImageAnimation = (id, setInViewport, isTablet, isMobile, theme) => { const dCards = gsap?.utils?.toArray(`div.asset--${id} div.asset-component`); imageTimelineAnimation = gsap.timeline({ ease: 'Power3.easeOut', paused: true, reversed: true, scrollTrigger: { end: (self) => !isTablet && !isMobile ? self.next().start - 10 : isMobile ? self.next().start : self.next().start - 50, fastScrollEnd: true, invalidateOnRefresh: true, onEnter: () => { setInViewport(true); }, onEnterBack: ({ isActive, animation }) => { if (isActive) { animation.scrollTrigger.vars.scrub = 2; reverseInitialImageAnimation(id, isTablet, isMobile); setInViewport(false); } }, onLeave: () => { if (dCards.length === 1) { setInViewport(false); } }, onLeaveBack: () => { firstImageGradientTween(id).reverse(); }, onToggle: async ({ isActive, getVelocity, direction, animation, progress }) => { if (!isActive && currentCount > 0 && direction === -1 && getVelocity() < 0) { await animation.progress(progress === 1 ? 1 : 0).pause(); gsap.set([`.asset--${id}:first-child`, `.optional--${id}:first-child`], { opacity: 1, visibility: 'visible', yPercent: 0, }); gsap.set([`.asset--${id}:not(:first-child)`, `.optional--${id}:not(:first-child)`], { opacity: 0, visibility: 'hidden', yPercent: 100, }); } }, pin: `.container--${id} div.ui-demo-container--${id}`, scrub: 2, start: () => (isMobile ? '5% 50%' : isTablet ? detectTabletOrientation() : '20% 55%'), trigger: `div.asset-container--${id} div.asset-${id}-0`, // markers: {startColor: 'blue', endColor: 'black'}, }, }); imageTimelineAnimation .fromTo( `div#device-${id} .transparent-border`, { duration: 0.5, opacity: 0.95, outline: 'none', }, { duration: 0.5, onStart: async (self) => { await initialImageAnimation(id, isTablet, isMobile); }, opacity: 1, outline: !isMobile && !isTablet ? '4px solid' : isMobile ? '1.72px solid' : '2px solid', } ) return imageTimelineAnimation; }; export const slideTween = (nextCard, nextSecondaryCard?) => gsap.fromTo( [nextCard, nextSecondaryCard], { autoAlpha: 0, duration: 1.25, paused: true, stagger: 0.1, yPercent: 100, }, { autoAlpha: 1, duration: 1.25, paused: true, stagger: 0.1, yPercent: 0, } ); export const onStartTweens = (currentIndex, nextIndex, textElements) => { slidePrevNextText(textElements[currentIndex], textElements[nextIndex]); const currentElements: any = textElements.filter((ele, i) => i !== currentIndex); gsap.set([...currentElements], { autoAlpha: 0, }); }; function checkIfAnyOverlap(rect1: any, rect2: any) { return !( rect1.right < rect2.left || rect1.left > rect2.right || rect1.bottom < rect2.top || rect1.top > rect2.bottom ); } export const checkForElementOverlap = (id) => { const element = document ?.querySelector(`section#${id} div.ui-demo-container--${id}`) ?.getBoundingClientRect(); const nextSiblingElement = document.querySelector(`section#${id}`)?.nextElementSibling?.getBoundingClientRect(); const mainElement = document.querySelector(`main`).getBoundingClientRect(); if ( (!!nextSiblingElement && checkIfAnyOverlap(element, nextSiblingElement)) || (!!mainElement && checkIfAnyOverlap(element, mainElement)) ) { return !!nextSiblingElement ? nextSiblingElement?.top - element?.bottom : mainElement?.bottom - element?.bottom; } else { return false; } }; export const handleBottomSpacing = (id, isTablet, isMobile) => { const element = document ?.querySelector(`section#${id} div.ui-demo-container--${id}`) ?.getBoundingClientRect(); const childContainer = document?.querySelector(`section#${id} div.child-container`)?.getBoundingClientRect(); const value = element?.bottom > childContainer?.bottom ? Math.round(element?.bottom - childContainer?.bottom) : Math.round(childContainer?.bottom - element?.bottom); if (!isMobile && !isTablet) { gsap.set(`section#${id}`, { marginBottom: element?.bottom > childContainer?.bottom ? (value > 0 ? 96 - value : 96 + value) : 96, }); } else if (!isMobile && isTablet) { gsap.set(`section#${id}`, { marginBottom: element?.bottom > childContainer?.bottom ? (value > 0 ? 64 - value : 64 + value) : 64, }); } }; export const goToCard = (progress: number, direction: number, index: number, currenIndex: number, nextCount: number, id: string) => { const dCards = gsap?.utils?.toArray(`div.parent-container div.asset--${id}`); const sCards = gsap?.utils?.toArray(`div.child-container div.optional--${id}`); const textElements = gsap?.utils?.toArray(`.tarea--${id}`); const currentCard: any = dCards[currenIndex]; const currentSecondaryCard: any = sCards[currenIndex]; const nextCard: any = dCards[nextCount]; const nextSecondaryCard: any = sCards[nextCount]; const targetCard: any = dCards[index]; const targetSecondaryCard: any = sCards[index]; if (index === currenIndex && direction === 1) { slideTween(nextCard, nextSecondaryCard) .play() .eventCallback('onStart', () => onStartTweens(index, nextCount, textElements)) .eventCallback('onComplete', () => { slideTween(currentCard, currentSecondaryCard).reverse(); }); } else if (index === currenIndex && direction === -1) { slideTween(currentCard, currentSecondaryCard).reverse(-0.5); slideTween(nextCard, nextSecondaryCard) .play('-=0.5') .eventCallback('onStart', () => onStartTweens(index, nextCount, textElements)); } else if (index > currenIndex) { slideTween(targetCard, targetSecondaryCard) .play() .eventCallback('onStart', () => onStartTweens(currenIndex, index, textElements)) .eventCallback('onComplete', () => { slideTween(currentCard, currentSecondaryCard).reverse(); }); } else if (index < currenIndex) { slideTween(targetCard, targetSecondaryCard) .play() .eventCallback('onStart', () => { const currentElements: any = textElements.filter((ele, i) => i !== currenIndex); gsap.set([...currentElements], { autoAlpha: 0, }); slidePrevNextTextReverse(textElements[currentCount], textElements[index]); }) .eventCallback('onComplete', () => { slideTween(currentCard, currentSecondaryCard).reverse(); }); } }; export const snapTimeline = (id, stateMethods) => { const { setActive, setInViewport, isTablet, isMobile } = stateMethods; const dCards = gsap?.utils?.toArray(`div.parent-container div.asset--${id}`); const sCards = gsap?.utils?.toArray(`div.child-container div.optional--${id}`); const textElements = gsap?.utils?.toArray(`.tarea--${id}`); if (dCards.length > 1) { const getEnd = () => { return isMobile ? 'bottom' : isTablet ? 'bottom top' : '+=5000'; }; snapScrollAnimation = gsap.timeline({ ease: 'Power3.easeOut', reversed: true, scrollTrigger: { end: () => getEnd(), endTrigger: `.ui-demo-container--${id} div.snap-last`, fastScrollEnd: true, invalidateOnRefresh: true, onEnterBack: () => { currentCount = dCards.length - 1; setActive(currentCount); setInViewport(true); }, onLeave: (self) => { currentCount = dCards.length - 1; setActive(currentCount); }, onLeaveBack: () => { currentCount = 0; setActive(0); setInViewport(true); }, onToggle: (self) => { finishOnFastLeave(self, dCards.length - 1, id); }, pin: `.container--${id} .ui-demo-container--${id}`, preventOverlaps: true, scrub: 2, // markers: true, snap: { duration: 1, ease: 'none', onComplete: ({ progress, direction }) => { const progressValue = +progress.toPrecision(2) * 100; const length = dCards.length - 1; const index = Math.round(+(+(progressValue / 100).toPrecision(1) * length).toPrecision(1)); currentCount = index; handleBottomSpacing(id, isMobile, isTablet); }, onStart: ({ progress, direction }) => { const progressValue = +progress.toPrecision(2) * 100; const length = dCards.length - 1; const index = Math.round(+(+(progressValue / 100).toPrecision(1) * length).toPrecision(1)); const nextCount = currentCount + 1 < dCards.length && direction === 1 ? currentCount + 1 : currentCount - 1 > 0 ? currentCount - 1 : 0; if (index > currentCount) { setActive(index); } else if (index < currentCount) { setActive(index); } else { setActive(nextCount); } goToCard(progress, direction, index, currentCount, nextCount, id); }, snapTo: 1 / (dCards?.length - 1), }, start: () => (isMobile ? 'top 9%' : isTablet ? 'top 4.5%' : 'top 5%'), trigger: `.ui-demo-container--${id} div.snap-first`, }, }); } return snapScrollAnimation; }; // tslint:disable-next-line: no-big-function export const initializeAnimation = async (id, stateMethods) => { const dCards = gsap?.utils?.toArray(`div.asset--${id} div.asset-component`); const secondaryCards = gsap?.utils?.toArray(`div.optional--${id}`); const { setInViewport, isTablet, isMobile, theme } = stateMethods; firstImageAnimation(id, setInViewport, isTablet, isMobile, theme); snapTimeline(id, stateMethods); const matchMediaRef: gsap.MatchMedia = gsap?.matchMedia(); const desktopTabletSet = () => { gsap.set(`.asset--${id}:first-child`, { opacity: 1, visibility: 'visible', yPercent: 0, }); gsap.set(`.asset--${id}:not(:first-child)`, { opacity: 0, visibility: 'hidden', yPercent: 100, }); gsap.set(`div#device-${id} div.asset-overlay`, { visibility: 'visible', opacity: 1 }); dCards.forEach((assetCard: HTMLDivElement, i) => { const secondaryCard: any = secondaryCards[i]; if (i === 0) { gsap.set(`div#device-${id} .outline-border`, { background: 'transparent', scale: isTablet ? 2 : 1.5, }); gsap.set(`div#device-${id} .transparent-border.${theme}`, { background: 'transparent', borderColor: 'transparent', borderRadius: '0px', }); gsap.set(`.tarea--${id}:first-child`, { opacity: 1, visibility: 'visible', x: 0, y: 0, }); gsap.set(secondaryCard, { opacity: 1, visibility: 'visible', yPercent: 0, }); } else { gsap.set(secondaryCard, { opacity: 0, visibility: 'hidden', yPercent: 100, }); } }); if (sCards.length === 0) { mainContainerTween(id, isTablet, isMobile).kill(); progressButtonTween(id).kill(); } if (dCards.length === 1) { progressButtonTween(id).kill(); } else if (dCards.length === 0) { fullScreenTween(id).kill(); progressButtonTween(id).kill(); } }; const mobileSet = () => { gsap.set(`.asset--${id}:first-child`, { opacity: 1, visibility: 'visible', yPercent: 0, }); gsap.set(`.asset--${id}:not(:first-child)`, { opacity: 0, visibility: 'hidden', yPercent: 100, }); gsap.set(`div#device-${id} div.asset-overlay`, { visibility: 'visible', opacity: 1 }); gsap.set( [`div#device-${id} div.child-container`, `div#device-${id} .full-screen`, `.progress-container--${id}`], { display: 'none' } ); childContainerTween(id, isTablet).kill(); fullScreenTween(id, isTablet).kill(); progressButtonTween(id).kill(); mainContainerTween(id, isTablet, isMobile).revert(); gsap.set(`div#device-${id} .outline-border`, { background: 'transparent', scale: 2, }); gsap.set(`div#device-${id} .transparent-border.${theme}`, { background: 'transparent', borderColor: 'transparent', borderRadius: '0px', }); gsap.set(`.tarea--${id}:first-child`, { opacity: 1, visibility: 'visible', x: 0, y: 0, }); }; matchMediaRef .add( [ '(min-width: 960px)', '(min-width: 1440px)', '(min-width: 1920px)', '(min-width: 768px) and (max-width: 1023px)', '(min-width: 768px) and (max-width: 1023px) and (orientation: landscape)', '(min-width: 1024px) and (max-width: 1180px) and (orientation: landscape)', ], () => desktopTabletSet() ) .add( [ '(min-width: 320px) and (max-width: 719px)', '(min-width: 320px) and (max-width: 719px) and (orientation: landscape)', '(max-height: 719px) and (orientation: landscape)', ], () => mobileSet() ); }; export let snapScrollAnimation: gsap.core.Timeline; export let imageTimelineAnimation: gsap.core.Timeline;
  19. Hi all. I have been tasked my by company to revamp our site. We have designs and a concept for a single-page site that makes use of animations tied to scroll progress. GSAP and Scrolltrigger has been amazing for this so far. At this point I have the full animation orchestrated from the top to the bottom of the page. Scrolling at a reasonable speed results in the desired effect. However scrolling too quickly or jumping to certain points on the page results in elements ending up in places where they shouldn't be. The animation is quite a complex one when all put together. It involves the same elements being animated multiple times, as they move around the page while scrolling. I've divided the single-page into various sections, and have a separate timeline that handles each section. I'm unable to share a full codepen as I'm not allowed to share certain information such as our assets, but I have included code below that I hope adequately shows my approach. I've tried various solutions suggested already on this forum, including: setting "immediateRender" and "overwrite", using only fromTo's, relative vs absolute values. I think that my mistake lies in my approach to the task, I believe I'm not employing the optimal practices in order to complete a complex animation of this nature. useEffect(() => { gsap.registerPlugin(ScrollTrigger); planetFloat(); landingPhase(); discoverPhase(); discussPhase(); decidePhase(); }, []); export const landingPhase = () => { gsap .timeline({ scrollTrigger: { trigger: ".scroll-trigger", start: "10% bottom", end: "+=2000", scrub: 0.25, }, }) // Move landing text off screen .to(".landing-text", { opacity: "-=1", x: "+=300", }) // Bring greatness text onto screen .fromTo( ".greatness-text", { autoAlpha: 0, x: -300 }, { autoAlpha: 1, x: 0, }, ">-50%" ) // Scale up discover system .fromTo( ".discover-system", { opacity: 0, scale: 0 }, { opacity: 1, scale: 1, }, // ">-60%" "<" ) // Telescope ledge rises into view .fromTo( ".telescope", { y: 350 }, { y: 0, }, // ">-60%" "<" ) // Greatness text descends below telescope ledge .to( ".greatness-text", { opacity: "-=1", y: "+=550", }, ">100%" ) // Journey text descends into view .fromTo( ".journey-text", { y: -550, autoAlpha: 0 }, { y: 0, autoAlpha: 1, }, ">-70%" ) // Beginning of system rearrange --> .to( "#moon-container", { x: "-=50", y: "-=100", scale: "-=0.7", overwrite: true }, ">100%" ) .to( "#galaxy-swirl-container", { x: "-=400", y: "+=50", rotate: 7, scale: "+=0.4", overwrite: true }, "<" ) .fromTo("#sun-container", { scale: 0 }, { scale: 0.3 }, "<") .to( "#ringed-planet-container", { x: "-=500", y: "+=100", overwrite: true }, "<" ) .fromTo("#red-planet-container", { scale: 0 }, { scale: 1 }, "<") .fromTo("#darkBlue-planet-container", { scale: 0 }, { scale: 1 }, "<") .to( "#lightBlue-planet-container", { x: "-=160", y: "+=240", scale: "+=0.5", overwrite: true }, "<" ) .to( "#dark-planet-container", { x: "+=50", y: "-=150", scale: "-=0.5", overwrite: true }, "<" ) .to( "#turquoise-planet-container", { x: "-=260", y: "+=60", scale: "+=1.5", overwrite: true }, "<" ) // <-- Ending of system rearrange // Telescope ledge zooms out of view .to( ".telescope", { y: "+=500", x: "-=800", }, "<" ) // Journey text zooms out of view .fromTo( ".journey-text", { y: 0, x: 0, }, { y: 500, x: -800, }, "<" ); }; export const discoverPhase = () => { gsap .timeline({ scrollTrigger: { trigger: ".scroll-trigger", start: "25% bottom", end: "+=2000", scrub: 0.25, }, }) // Phase 1 text moves in from the right .fromTo(".phase1-text", { x: 1500 }, { x: 1200 }, "") // Discover text fades in .fromTo( ".discover-text", { autoAlpha: 0, scale: 2.5 }, { autoAlpha: 1, scale: 2.5 }, "<" ) // Phase 1 text moves over the screen .to(".phase1-text", { x: "-=135%" }, ">100%") // Beginning of system rearrange --> .to( "#galaxy-swirl-container", { rotate: -15, x: "+=300", scale: "-=0.4", overwrite: true }, ">-50%" ) .to( "#sun-container", { x: "+=250", y: "+=25", scale: "-=0.05", overwrite: true }, "<" ) .to("#moon-container", { x: "+=250", overwrite: true }, "<") .to( "#lightBlue-planet-container", { x: "+=200", y: "-=50", scale: "-=0.5", overwrite: true }, "<" ) .to( "#dark-planet-container", { x: "+=200", y: "+=25", scale: "-=0.1", overwrite: true }, "<" ) .to( "#turquoise-planet-container", { x: "+=200", y: "-=75", scale: "-=0.5", overwrite: true, }, "<" ) .to( "#red-planet-container", { x: "+=400", y: "+=50", overwrite: true }, "<" ) .to( "#darkBlue-planet-container", { x: "+=400", y: "+=50", overwrite: true }, "<" ) .to( "#ringed-planet-container", { x: "+=450", scale: "-=0.2", overwrite: true }, "<" ) // <-- Ending of system rearrange // Discover text moves away with system .to( ".discover-text", { rotate: -25, x: "+=450", scale: "-=0.6", opacity: "-=1" }, "<" ) // Curiosity header text slides in .fromTo( ".curiosity-header-text", { x: -700, }, { x: 0 }, "<" ) // Curiosity paragraph 1 text slides in .fromTo( ".curiosity-paragraph1-text", { x: -700, }, { x: 0 }, ">-70%" ) // Curiosity paragraph 2 text slides in .fromTo( ".curiosity-paragraph2-text", { x: -700, }, { x: 0 }, ">-70%" ) // Beginning of system rearrange --> .to( "#lightBlue-planet-container", { x: "-=500", y: "+=500", scale: "+=15", overwrite: true, }, ">200%" ) .to( "#turquoise-planet-container", { x: "-=825", y: "+=30", scale: "+=1.5", overwrite: true, }, "<" ) .to( "#ringed-planet-container", { y: "-=50", x: "-=50", scale: "+=1", overwrite: true, }, "<" ) .to( "#red-planet-container", { x: "-=1500", opacity: "-=1", overwrite: true, }, "<" ) .to( "#darkBlue-planet-container", { x: "-=1500", opacity: "-=1", overwrite: true, }, "<" ) .to( "#dark-planet-container", { x: "-=900", y: "-=150", scale: "+=0.5", overwrite: true, }, "<" ) .to( "#moon-container", { y: "-=0", x: "-=200", scale: "+=0.5", overwrite: true, }, "<" ) .to( "#galaxy-swirl-container", { x: "-=1500", opacity: "-=1", scale: "+=10", overwrite: true, }, "<" ) .to( "#sun-container", { opacity: "-=1", x: "-=1500", y: "-=200", scale: "+=2", overwrite: true, }, "<" ) // <-- Ending of system rearrange // Curiosity header text moves off screen .to( ".curiosity-header-text", { x: "-=700", }, "<" ) // Curiosity paragraph 1 text moves off screen .to( ".curiosity-paragraph1-text", { x: "-=700", }, "<" ) // Curiosity paragraph 2 text moves off screen .to( ".curiosity-paragraph2-text", { x: "-=700", }, "<" ) // Phase 1 text moves off screen .to( ".phase1-text", { x: "-=1000", }, "<" ) // Discuss text fades up and in .fromTo( ".discuss-text", { autoAlpha: 0, scale: 0, y: 500, }, { autoAlpha: 1, scale: 2.5, y: 0, }, ">-50%" ) // Phase 2 texts slides on screen .fromTo( ".phase2-text", { x: -1700, }, { x: -800, }, "<" ); };
  20. Hi, Another alternative is to use overwrite in your mouse enter/leave animations so GSAP kills any animation that is affecting the same element and property: https://gsap.com/docs/v3/GSAP/Tween#special-properties overwrite If true, all tweens of the same targets will be killed immediately regardless of what properties they affect. If "auto", when the tween renders for the first time it hunt down any conflicts in active animations (animating the same properties of the same targets) and kill only those parts of the other tweens. Non-conflicting parts remain intact. If false, no overwriting strategies will be employed. Default: false. This code seems to work the way you expect: divs.forEach((div) => { // Select the span element inside the div const span = div.querySelector("span"); gsap.set(span, { scaleY: 0 }); // Add a mouseenter event listener to the div div.addEventListener("mouseenter", () => { // Animate the height of the span element from 0% to 100% gsap.to(span, { scaleY: 1, transformOrigin: "bottom center", ease: "power3.out", overwrite: true, duration: 0.5 }); }); // Add a mouseleave event listener to the div div.addEventListener("mouseleave", () => { // Animate the height of the span element from 100% to 0% gsap.to(span, { scaleY: 0, transformOrigin: "bottom center", ease: "power4.in", overwrite: true, duration: 0.4 }); }); }); Hopefully this helps. Happy Tweening!
  21. At first glance the rabbit hole did not seem that deep, I might be wrong when I apply it across my entire application (I already notice that I should replace the setTimeouts with a delay for instance). But in short, this is how I approached it. I have made a file that operates as a wrapper for gsap, it imports an external file that manages the state of the animations (a Pinia datastore in my case). Which has a boolean property called "showAnimations" to determine wether animations will be played or not. /services/gsap-wrapper.ts import gsap from "gsap" import appStore from "@/stores/app" const gsapWrapper = {...gsap} gsapWrapper.to = ( target: gsap.TweenTarget, durationOrVars: number | gsap.TweenVars, vars?: gsap.TweenVars ) => { let options = {} as gsap.TweenVars if (typeof durationOrVars === "number") { options.duration = durationOrVars } else { vars = durationOrVars } options = { ...options, ...vars, } as gsap.TweenVars // Pinia datastore const app = appStore() // Overwrite duration & delay when animations are not allowed if (!app.showAnimations) { options.duration = 0 options.delay = 0 options.ease = "none" if (typeof options.stagger == "number") { options.stagger = 0 } else if (typeof options.stagger === "object" && options.stagger !== null) { options.stagger.each = 0 } } return gsap.to(target, options) } gsapWrapper.fromTo = ( target: gsap.TweenTarget, durationOrFromVars: number | gsap.TweenVars, fromOrToVars: gsap.TweenVars, toVars?: gsap.TweenVars ) => { let options = {} as gsap.TweenVars let fromVars = fromOrToVars if (typeof durationOrFromVars === "number") { options.duration = durationOrFromVars fromVars = fromOrToVars } else { toVars = fromOrToVars fromVars = durationOrFromVars } options = { ...options, ...toVars, } as gsap.TweenVars // Pinia datastore const app = appStore() // Overwrite duration & delay when animations are not allowed if (!app.showAnimations) { options.duration = 0 options.delay = 0 options.ease = "none" if (typeof options.stagger == "number") { options.stagger = 0 } else if (typeof options.stagger === "object" && options.stagger !== null) { options.stagger.each = 0 } } return gsap.fromTo(target, { ...fromVars, }, options) } export default gsapWrapper In the other files where I normally include gsap via import gsap from "gsap", I now simply import it as followed: import gsap from "/services/gsap-wrapper" This approach allows me to enable/disable all gsap animations from 1 single location which seem to have the following up- and downsides. Upsides I have on boolean variable that I can modify to disable ALL animations throughout my application The code is relatively simple, and can be easily adjusted and expanded It uses the default gsap library, so unless breaking changes occur in the gsap.to method. Everything will remain working with future gsap updates Downsides It is applicable to ALL gsap.to methods. As a workaround you could import both the gsap-wrapper and gsap into a file, but that could easily become a slippery slope It can be quite a hassle to figure out how the wrapper function should be written to respect the original gsap method and its types
  22. I'm not sure what you mean by "properly" - from what I can tell, it's doing everything exactly properly. Are you trying to find all the tweens that affect a particular target and kill them? If so, you can use gsap.killTweensOf(). If you want to just find the tweens of a particular target, you can use gsap.getTweensOf(). overwrite: "auto" runs the first time the tween renders, and it finds ONLY the in-progress tweens that are affecting the same individual properties of the same target, and kills those (just the individual properties that overlap). If you set overwrite: true, it'll find all of the tweens of the same target(s) regardless of what properties overlap, and kill them immediately. So with the above tools, you should be able to accomplish pretty much anything you need.
  23. Hi Rodrigo, I did some experiments after reading through your response. The animation goes back to normal after the window is resized. However, we can't just ask the visitors to resize the window to see the effect, right? And, I am unsure what you mean by "the order things are called". Assuming I am right, I moved the About section above all other animations. However, the problem still occurs. Then, I try to comment out the command lines one by one. I noticed that as long as the "homePlanet" animation is not calling. Everything will work just fine, as you showed me in your reply. So, I started asking myself about my looping rotation and its speed. Please see my codes below. planet .to(".dot-line", { repeat: -1, rotation: "+=360", duration: 100, ease: "none", transformOrigin: "center center" }) .to(".planet", { repeat: -1, rotation: "+=360", ease: "none", svgOrigin: "431.92 431.92", duration: 30, overwrite: "auto" }, 0) .to(".planet-ab", { repeat: -1, rotation: "+=360", ease: "none", svgOrigin: "566.76 566.76", duration: 60, overwrite: "auto" }, 0) I am using duration to control its speed. I wonder if it could be the duration that caused the issue. This looping feature involved 2 sections, which you can see in the below codepen link. https://codepen.io/danclp/pen/KKEarwe The rotation works as a continuing animation, even after it has been scroll-triggered away in the first section. You can still see the rotation animation available in the second section (the sliding text section). Did I code correctly, or does it have another way of calling when we want it to animate continuously? Also, should I use duration or something else when I want to slow down the rotation speed? Can you give me some advice? Thank you.
  24. ho sorry , oki after many test i just starting found correct solutions: `overwrite: 'auto'` => ` overwrite: true,` https://codepen.io/djmisterjon/pen/BabpgPx?editors=0011 i will need make more deep test to see if this broke behaviors in my app !? but seem promising, de delay animation seem override thanks
  25. 120Tracking Prevention blocked access to storage for <URL>. require.js:168 Uncaught Error: Mismatched anonymous define() module: function(e){"use strict";function _inheritsLoose(t,e){t.prototype=Object.create(e.prototype),(t.prototype.constructor=t).__proto__=e}function _assertThisInitialized(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}function n(t){return"string"==typeof t}function o(t){return"function"==typeof t}function p(t){return"number"==typeof t}function q(t){return void 0===t}function r(t){return"object"==typeof t}function s(t){return!1!==t}function t(){return"undefined"!=typeof window}function u(t){return o(t)||n(t)}function K(t){return(l=pt(t,at))&&ie}function L(t,e){return console.warn("Invalid property",t,"set to",e,"Missing plugin? gsap.registerPlugin()")}function M(t,e){return!e&&console.warn(t)}function N(t,e){return t&&(at[t]=e)&&l&&(l[t]=e)||at}function O(){return 0}function Y(t){var e,i,n=t[0];if(r(n)||o(n)||(t=[t]),!(e=(n._gsap||{}).harness)){for(i=dt.length;i--&&!dt[i].targetTest(n););e=dt[i]}for(i=t.length;i--;)t[i]&&(t[i]._gsap||(t[i]._gsap=new Ft(t[i],e)))||t.splice(i,1);return t}function Z(t){return t._gsap||Y(yt(t))[0]._gsap}function $(t,e){var r=t[e];return o(r)?t[e]():q(r)&&t.getAttribute(e)||r}function _(t,e){return(t=t.split(",")).forEach(e)||t}function aa(t){return Math.round(1e5*t)/1e5||0}function ba(t,e){for(var r=e.length,i=0;t.indexOf(e[i])<0&&++i<r;);return i<r}function ca(t,e,r){var i,n=p(t[1]),a=(n?2:1)+(e<2?0:1),o=t[a];if(n&&(o.duration=t[1]),o.parent=r,e){for(i=o;r&&!("immediateRender"in i);)i=r.vars.defaults||{},r=s(r.vars.inherit)&&r.parent;o.immediateRender=s(i.immediateRender),e<2?o.runBackwards=1:o.startAt=t[a-1]}return o}function da(){var t,e,r=ot.length,i=ot.slice(0);for(ut={},t=ot.length=0;t<r;t++)(e=i[t])&&e._lazy&&(e.render(e._lazy[0],e._lazy[1],!0)._lazy=0)}function ea(t,e,r,i){ot.length&&da(),t.render(e,r,i),ot.length&&da()}function fa(t){var e=parseFloat(t);return(e||0===e)&&(t+"").match(nt).length<2?e:t}function ga(t){return t}function ha(t,e){for(var r in e)r in t||(t[r]=e[r]);return t}function ia(t,e){for(var r in e)r in t||"duration"===r||"ease"===r||(t[r]=e[r])}function ka(t,e){for(var i in e)t[i]=r(e[i])?ka(t[i]||(t[i]={}),e[i]):e[i];return t}function la(t,e){var r,i={};for(r in t)r in e||(i[r]=t[r]);return i}function ma(t){var e=t.parent||F,r=t.keyframes?ia:ha;if(s(t.inherit))for(;e;)r(t,e.vars.defaults),e=e.parent||e._dp;return t}function pa(t,e,r,i){void 0===r&&(r="_first"),void 0===i&&(i="_last");var n=e._prev,a=e._next;n?n._next=a:t[r]===e&&(t[r]=a),a?a._prev=n:t[i]===e&&(t[i]=n),e._next=e._prev=e.parent=null}function qa(t,e){!t.parent||e&&!t.parent.autoRemoveChildren||t.parent.remove(t),t._act=0}function ra(t){for(var e=t;e;)e._dirty=1,e=e.parent;return t}function ua(t){return t._repeat?_t(t._tTime,t=t.duration()+t._rDelay)*t:0}function wa(t,e){return(t-e._start)*e._ts+(0<=e._ts?0:e._dirty?e.totalDuration():e._tDur)}function xa(t){return t._end=aa(t._start+(t._tDur/Math.abs(t._ts||t._rts||B)||0))}function ya(t,e){var r;if((e._time||e._initted&&!e._dur)&&(r=wa(t.rawTime(),e),(!e._dur||gt(0,e.totalDuration(),r)-e._tTime>B)&&e.render(r,!0)),ra(t)._dp&&t._initted&&t._time>=t._dur&&t._ts){if(t._dur<t.duration())for(r=t;r._dp;)0<=r.rawTime()&&r.totalTime(r._tTime),r=r._dp;t._zTime=-B}}function za(t,e,r,i){return e.parent&&qa(e),e._start=aa(r+e._delay),e._end=aa(e._start+(e.totalDuration()/Math.abs(e.timeScale())||0)),function _addLinkedListItem(t,e,r,i,n){void 0===r&&(r="_first"),void 0===i&&(i="_last");var a,s=t[i];if(n)for(a=e[n];s&&s[n]>a;)s=s._prev;s?(e._next=s._next,s._next=e):(e._next=t[r],t[r]=e),e._next?e._next._prev=e:t[i]=e,e._prev=s,e.parent=e._dp=t}(t,e,"_first","_last",t._sort?"_start":0),t._recent=e,i||ya(t,e),t}function Aa(t,e){return(at.ScrollTrigger||L("scrollTrigger",e))&&at.ScrollTrigger.create(e,t)}function Ba(t,e,r,i){return qt(t,e),t._initted?!r&&t._pt&&(t._dur&&!1!==t.vars.lazy||!t._dur&&t.vars.lazy)&&d!==Mt.frame?(ot.push(t),t._lazy=[e,i],1):void 0:1}function Ea(t,e,r){var i=t._repeat,n=aa(e)||0;return t._dur=n,t._tDur=i?i<0?1e10:aa(n*(i+1)+t._rDelay*i):n,t._time>n&&(t._time=n,t._tTime=Math.min(t._tTime,t._tDur)),r||ra(t.parent),t.parent&&xa(t),t}function Fa(t){return t instanceof Bt?ra(t):Ea(t,t._dur)}function Ha(t,e){var r,i,a=t.labels,s=t._recent||mt,o=t.duration()>=E?s.endTime(!1):t._dur;return n(e)&&(isNaN(e)||e in a)?"<"===(r=e.charAt(0))||">"===r?("<"===r?s._start:s.endTime(0<=s._repeat))+(parseFloat(e.substr(1))||0):(r=e.indexOf("="))<0?(e in a||(a[e]=o),a[e]):(i=+(e.charAt(r-1)+e.substr(r+1)),1<r?Ha(t,e.substr(0,r-1))+i:o+i):null==e?o:+e}function Ia(t,e){return t||0===t?e(t):e}function Ka(t){return(t+"").substr((parseFloat(t)+"").length)}function Na(t,e){return t&&r(t)&&"length"in t&&(!e&&!t.length||t.length-1 in t&&r(t[0]))&&!t.nodeType&&t!==i}function Qa(t){return t.sort(function(){return.5-Math.random()})}function Ra(t){if(o(t))return t;var p=r(t)?t:{each:t},_=zt(p.ease),m=p.from||0,g=parseFloat(p.base)||0,v={},e=0<m&&m<1,y=isNaN(https://requirejs.org/docs/errors.html#mismatch at makeError (require.js:168:17) at intakeDefines (require.js:1254:36) at Object.localRequire [as require] (require.js:1446:21) at requirejs (require.js:1797:24) at custom.js:32:1 makeError @ require.js:168 intakeDefines @ require.js:1254 localRequire @ require.js:1446 requirejs @ require.js:1797 (anonymous) @ custom.js:32 testrahul.js:1 hiiiiiiiiiiiiiiiiiiiiiiiii testrahul.js:42 Service Worker registered with scope: https://totalfood.greenhonchos.in/ totalfood.greenhonchos.in/:1100 [Intervention] Images loaded lazily and replaced with placeholders. Load events are deferred. See https://go.microsoft.com/fwlink/?linkid=2048113 customtest.js:34 gsap test[object Object] customtest.js:35 {"Back":{},"Bounce":{},"CSSPlugin":{"name":"css","aliases":{"autoAlpha":"opacity,visibility","scale":"scaleX,scaleY","alpha":"opacity","transform":"x,y,z,scale,scaleX,scaleY,xPercent,yPercent,rotation,rotationX,rotationY,skewX,skewY","translateX":"x","translateY":"y","translateZ":"z","rotate":"rotation","rotationZ":"rotation","rotateZ":"rotation","rotateX":"rotationX","rotateY":"rotationY"},"core":{}},"Circ":{},"Cubic":{},"Elastic":{},"Expo":{},"Linear":{},"Power0":{},"Power1":{},"Power2":{},"Power3":{},"Power4":{},"Quad":{},"Quart":{},"Quint":{},"Sine":{},"SteppedEase":{},"Strong":{},"default":{"utils":{},"effects":{},"ticker":{"time":0.537,"frame":5,"_listeners":[null]},"plugins":{},"globalTimeline":{"vars":{"sortChildren":false,"defaults":{"duration":0.5,"overwrite":false,"delay":0},"autoRemoveChildren":true,"id":"root","smoothChildTiming":true},"_delay":0,"_repeat":0,"_ts":1,"_dur":0,"_tDur":0,"labels":{},"smoothChildTiming":true,"autoRemoveChildren":true,"_sort":false,"_dirty":0,"_zTime":0.006,"_tTime":0.537,"_time":0.537,"_act":false,"_initted":1},"core":{},"version":"3.3.1"},"gsap":{"utils":{},"effects":{},"ticker":{"time":0.537,"frame":5,"_listeners":[null]},"plugins":{},"globalTimeline":{"vars":{"sortChildren":false,"defaults":{"duration":0.5,"overwrite":false,"delay":0},"autoRemoveChildren":true,"id":"root","smoothChildTiming":true},"_delay":0,"_repeat":0,"_ts":1,"_dur":0,"_tDur":0,"labels":{},"smoothChildTiming":true,"autoRemoveChildren":true,"_sort":false,"_dirty":0,"_zTime":0.006,"_tTime":0.537,"_time":0.537,"_act":false,"_initted":1},"core":{},"version":"3.3.1"}} customtest.js:36 Uncaught TypeError: gsap.to is not a function at customtest.js:36:14 at Object.execCb (require.js:1696:33) at Module.check (require.js:883:51) at Module.<anonymous> (require.js:1139:34) at require.js:134:23 at require.js:1189:21 at each (require.js:59:31) at Module.emit (require.js:1188:17) at Module.check (require.js:938:30) at Module.enable (require.js:1176:22) (anonymous) @ customtest.js:36 execCb @ require.js:1696 check @ require.js:883 (anonymous) @ require.js:1139 (anonymous) @ require.js:134 (anonymous) @ require.js:1189 each @ require.js:59 emit @ require.js:1188 check @ require.js:938 enable @ require.js:1176 init @ require.js:788 (anonymous) @ require.js:982 (anonymous) @ require.js:134 (anonymous) @ require.js:1189 each @ require.js:59 emit @ require.js:1188 check @ require.js:938 enable @ require.js:1176 init @ require.js:788 (anonymous) @ require.js:1014 (anonymous) @ require.js:134 runCallbacks @ domReady.js:24 callReady @ domReady.js:35 pageLoaded @ domReady.js:50 setTimeout (async) (anonymous) @ domReady.js:94 execCb @ require.js:1696 check @ require.js:883 enable @ require.js:1176 init @ require.js:788 callGetModule @ require.js:1203 completeLoad @ require.js:1590 onScriptLoad @ require.js:1717 load (async) req.load @ require.js:1942 load @ require.js:1685 load @ require.js:834 fetch @ require.js:824 check @ require.js:856 enable @ require.js:1176 enable @ require.js:1557 callPlugin @ require.js:1098 fetch @ require.js:824 check @ require.js:856 enable @ require.js:1176 enable @ require.js:1557 (anonymous) @ require.js:1161 (anonymous) @ require.js:134 each @ require.js:59 enable @ require.js:1113 init @ require.js:788 (anonymous) @ require.js:1460 setTimeout (async) req.nextTick @ require.js:1815 localRequire @ require.js:1449 requirejs @ require.js:1797 (anonymous) @ customtest.js:29 current_location_modal.js:11 custom-checkout location/index/index/ current_location_modal.js:21 test modal compat.js:43 Fallback to JQueryUI Compat activated. Your store is missing a dependency for a jQueryUI widget. Identifying and addressing the dependency will drastically improve the performance of your site. (anonymous) @ compat.js:43 execCb @ require.js:1696 check @ require.js:883 (anonymous) @ require.js:1139 (anonymous) @ require.js:134 (anonymous) @ require.js:1189 each @ require.js:59 emit @ require.js:1188 check @ require.js:938 (anonymous) @ require.js:1139 (anonymous) @ require.js:134 (anonymous) @ require.js:1189 each @ require.js:59 emit @ require.js:1188 check @ require.js:938 enable @ require.js:1176 init @ require.js:788 (anonymous) @ require.js:1014 (anonymous) @ require.js:134 (anonymous) @ mixins.js:129 execCb @ require.js:1696 check @ require.js:883 (anonymous) @ require.js:1139 (anonymous) @ require.js:134 (anonymous) @ require.js:1189 each @ require.js:59 emit @ require.js:1188 check @ require.js:938 (anonymous) @ require.js:1139 (anonymous) @ require.js:134 (anonymous) @ require.js:1189 each @ require.js:59 emit @ require.js:1188 check @ require.js:938 enable @ require.js:1176 init @ require.js:788 (anonymous) @ require.js:1014 (anonymous) @ require.js:134 (anonymous) @ mixins.js:129 execCb @ require.js:1696 check @ require.js:883 (anonymous) @ require.js:1139 (anonymous) @ require.js:134 (anonymous) @ require.js:1189 each @ require.js:59 emit @ require.js:1188 check @ require.js:938 (anonymous) @ require.js:1139 (anonymous) @ require.js:134 (anonymous) @ require.js:1189 each @ require.js:59 emit @ require.js:1188 check @ require.js:938 enable @ require.js:1176 init @ require.js:788 (anonymous) @ require.js:1014 (anonymous) @ require.js:134 (anonymous) @ mixins.js:129 execCb @ require.js:1696 check @ require.js:883 (anonymous) @ require.js:1139 (anonymous) @ require.js:134 (anonymous) @ require.js:1189 each @ require.js:59 emit @ require.js:1188 check @ require.js:938 enable @ require.js:1176 init @ require.js:788 callGetModule @ require.js:1203 completeLoad @ require.js:1590 onScriptLoad @ require.js:1717 load (async) req.load @ require.js:1942 load @ require.js:1685 load @ require.js:834 fetch @ require.js:824 check @ require.js:856 enable @ require.js:1176 enable @ require.js:1557 (anonymous) @ require.js:1161 (anonymous) @ require.js:134 each @ require.js:59 enable @ require.js:1113 init @ require.js:788 (anonymous) @ require.js:1460 setTimeout (async) req.nextTick @ require.js:1815 localRequire @ require.js:1449 load @ mixins.js:128 (anonymous) @ require.js:1095 (anonymous) @ require.js:134 on @ require.js:517 callPlugin @ require.js:955 fetch @ require.js:824 check @ require.js:856 enable @ require.js:1176 enable @ require.js:1557 (anonymous) @ require.js:1161 (anonymous) @ require.js:134 each @ require.js:59 enable @ require.js:1113 init @ require.js:788 callGetModule @ require.js:1203 completeLoad @ require.js:1590 onScriptLoad @ require.js:1717 load (async) req.load @ require.js:1942 load @ require.js:1685 load @ require.js:834 fetch @ require.js:824 check @ require.js:856 enable @ require.js:1176 enable @ require.js:1557 (anonymous) @ require.js:1161 (anonymous) @ require.js:134 each @ require.js:59 enable @ require.js:1113 init @ require.js:788 (anonymous) @ require.js:1460 setTimeout (async) req.nextTick @ require.js:1815 localRequire @ require.js:1449 load @ mixins.js:128 (anonymous) @ require.js:1095 (anonymous) @ require.js:134 on @ require.js:517 callPlugin @ require.js:955 fetch @ require.js:824 check @ require.js:856 enable @ require.js:1176 enable @ require.js:1557 (anonymous) @ require.js:1161 (anonymous) @ require.js:134 each @ require.js:59 enable @ require.js:1113 init @ require.js:788 callGetModule @ require.js:1203 completeLoad @ require.js:1590 onScriptLoad @ require.js:1717 load (async) req.load @ require.js:1942 load @ require.js:1685 load @ require.js:834 fetch @ require.js:824 check @ require.js:856 enable @ require.js:1176 enable @ require.js:1557 (anonymous) @ require.js:1161 (anonymous) @ require.js:134 each @ require.js:59 enable @ require.js:1113 init @ require.js:788 callGetModule @ require.js:1203 completeLoad @ require.js:1590 onScriptLoad @ require.js:1717 load (async) req.load @ require.js:1942 load @ require.js:1685 load @ require.js:834 fetch @ require.js:824 check @ require.js:856 enable @ require.js:1176 enable @ require.js:1557 (anonymous) @ require.js:1161 (anonymous) @ require.js:134 each @ require.js:59 enable @ require.js:1113 init @ require.js:788 (anonymous) @ require.js:1460 setTimeout (async) req.nextTick @ require.js:1815 localRequire @ require.js:1449 requirejs @ require.js:1797 (anonymous) @ (index):418
×
×
  • Create New...