Jump to content
Search Community

Search the Community

Showing results for tags 'timeline'.

  • 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...

Found 562 results

  1. Hi GreenSock team 👋 I'm working with Next.js 15 and trying to orchestrate animations across multiple components using a shared masterTimelinethrough context. Each component defines its own gsap.timeline() and then adds it to the global timeline via masterTimeline.add(). For example: I have two components: Boxand Nav. - Box has its tl with 4 tweens and inserts a label after the second tween (addLabel('afterSecondTween')). - Nav defines its own timeline and tries to insert it at that label inside the master timeline using masterTimeline.add(navTL, 'afterSecondTween'). 🎯 My goal is to synchronize timelines between different components, so that they run in sequence or in specific positions. 💣 The result: Nav always animates at the start of the timeline. ✅ I’ve confirmed that: - The Nav timeline is added with the same label name. - But it still plays immediately (as if the label had time = 0). 💬 My question is: Is it correct to insert timelines at labels from other components in GSAP + React? Is this synchronization possible? What is the correct or recommended way to synchronize animations between different components in GSAP and React? Is this pattern okay: 1. Each component creates its own timeline 2. One of them defines a label at a specific point 3. Another component inserts its timeline at that label Or... is there a better / more robust way to orchestrate animations across components in React using GSAP? Thanks in advance for your insights 🙏 Here’s a minimal CodePen that replicates the problem: 📎 CodePen
  2. arno.oost

    Applying dotLottie-web on GSAP Timeline

    I'm working on an assignment for school. When the page loads in, it'll reveal the "hero image" (main screen) bit by bit automatically without requiring user assistance. Now I'm trying to integrate my dotLottie animation into the timeline but I'm having a really hard time doing so. I've scanned this forum for any possible answer, asked generative AI bots as well as classmates but nobody's solution seems to work. Here's my current "animations.js" file. I'm building a Vite site and have GSAP & dotLottie-web imported through NPM. import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; import { DotLottie } from '@lottiefiles/dotlottie-web'; gsap.registerPlugin(ScrollTrigger); const heroImgLottie = new DotLottie({ autoplay: false, loop: false, canvas: document.querySelector('#heroIMG'), src: "src/assets/lottie/heroimg.lottie" }); let hero_tl = gsap.timeline({ onComplete: heroImgLottie.play(), }); // Loader hero_tl.to('.loader_content', { duration: 0.25, delay: 3.5, opacity: 0, }) hero_tl.to('.loader_bar', { duration: 1.5, height: 0, stagger: { amount: 0.5, }, ease: "power4.inOut", }) hero_tl.to('.loader', { duration: 0, display:"none"}) hero_tl.from('.hero_title', { duration: .5, y: 100, opacity: 0, ease: "power4.out", }) hero_tl.to('.nav_options', { duration: .5, opacity: 1, ease: "power4.inOut", })
  3. After reading react-advanced for several times, having chatgpt, deepseek and claude helping me to debug and trying my best I decide to create minimal demo to ask for help. I also did search forums but I didn't find clear solution for my problem that is not some kind of overengineering that I dont even understand. I created parent component (App.jsx) which creates the timeline. I created two child components, Heading.jsx and Loader.jsx and I pass them timeline with prop drilling (like gsap react-advanced article suggest). In each child, with useGSAP hook and timeline.add I add proper animations to timeline. I want Loader.jsx animation to run first and only then Heading.jsx. How do I do it? Obviously if I swap component order in DOM (in app.jsx) I can make Loader.jsx run first, but this will get messy in real project where I have more components and animations to add in timeline, and I also dont want to change my DOM order. I tried with labels but it didnt help me at all. I obviously dont want to use fixed seconds to decide what will run when, because real timeline is much more complex than these two components. I just want a way to control order of these animations, and let timeline handle when animation is finished and when next one will run. How do I control sequence of animations inside timeline that is created in parent component, and where child component add animations to parent timeline? Demo: https://stackblitz.com/edit/gsap-react-basic-f48716-kbuaghjm?file=src%2FApp.js,src%2Fcomponents%2FLoader%2FLoader.jsx,src%2Fcomponents%2FHeading%2FHeading.jsx Thank you
  4. Pau Ferrer

    Scroll Trigger Animation problems [newie]

    Hi there!! 👋🏻 I am using GSAP for the first time and I am loving it!! But I would do with some help on a slider like animation I am creating for a client. This is done in Webflow using Saddle Framework. I will share Read Only link at the bottom of the message, but first some context. The client wants a slider with 2 sets of cards that animates on scroll. We use a switch to go from one slider to the other and here is where I am having a problem... When I click on the switch a new timeline gets set creating a timeline hell situation that scales the more you switch between the 2 sliders... I've tried to kill the tweens with ".killTweenOf()", to use the timeline object and kill it to reset it, and nothing seams to work... Here is my JavaScript: // wait for DOM and scripts to load window.addEventListener('load', ()=> { // GSAP Services Slider Switch Animation const section = document.querySelector('[bs-servicesSlider-element="section"]') const switchButton = section.querySelector('[bs-switchButton-element="switch"]') const toggle = switchButton.querySelector('[bs-switchButton-element="toggle"]') const leftText = switchButton.querySelector('[bs-switchButton-element="leftText"]') const rightText = switchButton.querySelector('[bs-switchButton-element="rightText"]') const retailerTrack = document.querySelector('[bs-servicesSlider-element="retailerTrack"]') const brandTrack = document.querySelector('[bs-servicesSlider-element="brandTrack"]') const items = [...document.querySelector('[bs-servicesSlider-element="list"]').children] const retailerItems = items.filter(item => item.children[1].innerHTML === 'Retailer') retailerItems[retailerItems.length - 1].style.borderRight = "none" retailerTrack.append(...retailerItems) const brandItems = items.filter(item => item.children[1].innerHTML === 'Brand') brandItems[brandItems.length - 1].style.borderRight = "none" brandTrack.append(...brandItems) const retailerProgressBar = section.querySelector('[bs-servicesSlider-element="retailerProgressBar"]') const brandProgressBar = section.querySelector('[bs-servicesSlider-element="brandProgressBar"]') let click = 0 // GSAP Service Slider Scroll Animation const commons = { duration: .4, ease: "circ.inOut" } const scrollTriggerCommons = { start: 'top 25%', end: '200% 25%', scrub: true, markers: true, toggleActions: 'play pause reverse pause' } const retailerStrollTrigger = { trigger: retailerTrack, ...scrollTriggerCommons } const brandScrollTrigger = { trigger: brandTrack, ...scrollTriggerCommons } const setSliderAnimation = () => { const track = click === 0 ? retailerTrack : brandTrack const progressBar = click === 0 ? retailerProgressBar : brandProgressBar const scrollTrigger = click === 0 ? retailerStrollTrigger : brandScrollTrigger const trackPosition = window.innerWidth - track.offsetWidth gsap.to(track, { x: trackPosition, ease: commons.ease, scrollTrigger: scrollTrigger }) trackPosition === 0 ? progressBar.parentElement.classList.add('u-hide') : progressBar.parentElement.classList.remove('u-hide') gsap.to(progressBar, { width: progressBar.parentElement.offsetWidth, ease: commons.ease, scrollTrigger: scrollTrigger }) } // GSAP Toggle Animation const toggleAnimation = () => { gsap.to(toggle, { xPercent: click === 0 ? 0 : 100, }) setTimeout(() => { if(click === 0) { rightText.classList.add('u-hide') leftText.classList.remove('u-hide') } if(click === 1) { leftText.classList.add('u-hide') rightText.classList.remove('u-hide') } }, 200) } // GSAP Theme Animation const theme = { lightGrey: '#f0f0f0', darkGrey: '#232323', yellow: '#e8f83d' } const themeAnimation = () => { gsap.to(section, { backgroundColor: click === 0 ? theme.yellow : theme.darkGrey, color: click === 0 ? theme.darkGrey : theme.lightGrey, ...commons }) gsap.to(section.querySelector('.subheading_line'), { backgroundColor: click === 0 ? theme.darkGrey : theme.lightGrey, ...commons }) gsap.to(switchButton, { backgroundColor: click === 0 ? theme.darkGrey : theme.yellow, color: click === 0 ? theme.lightGrey : theme.darkGrey, ...commons }) gsap.to(toggle, { backgroundColor: click === 0 ? theme.lightGrey : theme.darkGrey, color: click === 0 ? theme.darkGrey : theme.lightGrey, ...commons }) gsap.to([...retailerTrack.children, ...brandTrack.children], { borderColor: click === 0 ? theme.darkGrey : theme.lightGrey, ...commons }) } // GSAP Switch Click Animations const changeTrack = () => { gsap.to(click === 0 ? brandTrack : retailerTrack, { opacity: 0, ...commons }) if(click === 0) { brandTrack.classList.add('u-hide') retailerTrack.classList.remove('u-hide') retailerProgressBar.classList.remove('u-hide') brandProgressBar.classList.add('u-hide') } else { retailerTrack.classList.add('u-hide') brandTrack.classList.remove('u-hide') retailerProgressBar.classList.add('u-hide') brandProgressBar.classList.remove('u-hide') } gsap.to(click === 0 ? retailerTrack : brandTrack, { opacity: 1, ...commons }) } switchButton.onclick = (event) => { event.preventDefault() click = click === 0 ? 1 : 0 toggleAnimation() themeAnimation() changeTrack() gsap.to(window, { ...commons, scrollTo: { y: "#service-slider_outer", offsetY: 80, autoKill: true }, }) gsap.killTweensOf([retailerTrack, brandTrack], "x") setSliderAnimation() } // Resizing function const displayedCards = { desktop: 3, tablet: 2, mobile: 1 } const resizeTrack = (screenWidth, track) => { let cardsDisplayed = displayedCards.desktop if(screenWidth <= 991) { cardsDisplayed = displayedCards.tablet } if(screenWidth <= 568) { cardsDisplayed = displayedCards.mobile } track.style.width = `${(screenWidth / cardsDisplayed) * track.children.length}px` } // Init Animation resizeTrack(window.innerWidth, retailerTrack) resizeTrack(window.innerWidth, brandTrack) changeTrack() themeAnimation() setSliderAnimation() window.onresize = () => { resizeTrack(window.innerWidth, retailerTrack) resizeTrack(window.innerWidth, brandTrack) themeAnimation() changeTrack() setSliderAnimation() } }) You can find the elements in the Webflow project under "services-slider_outer", and the first section inside the inner wrapper has the JS object with the current code. Please, I need help as this is a key element of the project and I cannot create this animation with Webflow's animations since I need to dynamically change the width of the scroll animation. Thanks in advance!!! Link: https://preview.webflow.com/preview/buzket-space-v2?utm_medium=preview_link&utm_source=designer&utm_content=buzket-space-v2&preview=ff7a7c3ed6298bc1e243bd83225520d8&workflow=preview
  5. Hi guys hope you are doing good. Iam facing issue while working with my project iam trying to add dynamic section to existing one which already have scroll trigger and animation executed new section too have animation. when i add this new section its break animation of below section and add blank spacing as well in my production project it stop the below animation too. i have some sort of builder customizer so that when i changed content too it first removed the section and then append it the same position. e.g.. if section is placed over 3rd position then after content change it again added on same position when its added it give blank space for below section which have scroll trigger initialized as well stop the animation performed on it. I can't kill all trigger and the reinitialize all section again as it will compromise the performance by removing and adding animation for all section again and again. Please note - animation only break section below the newly added section. Tried with refresh each scrolltrigger again but its not worked. using forcefully refresh [ScrollTrigger.refresh(true);] Thanks in advance for any help or suggestion
  6. h_ivanov

    Smooth snake segments problem

    Hello everyone, I have the problem you can see on the video. When i pause the game the snake segments are correctly positioned, but when its running and a movement is made the segments are washing and not synced correctly. If i remove the duration the snake movement starts to be laggy and it is not smooth. At codepen i uploaded render.js as a HTML, main.js where we use ticker to init the game start as CSS and snake.js as JS where we care about the snake animations. Untitled22.mov
  7. code-im-perfect

    Weird CSS rotation after timeline transforms

    I have attached a simple recreation of the bug that I'm facing, there is a much more complicated timeline so cannot shift to CSS only animation. As you can see in the demo, rotation works perfectly fine with gsap, but css transforms it, without considering the transform, is there any way I can "apply" the gsap transforms as CSS at the end of the timeline and just remove all the previous gsap effects? Anyways, would separate infinite gsap timeline be less efficient than an infinite CSS animation? cuz that would be a lot simpler to apply.
  8. Hey all! This feels like it should be simple enough to do and yet I can't figure it out or find an answer in the forums. When you scroll down, the bars scale up until they reach their full height at the end of the 'body'. What I want to simply do is have them 'stagger' on scrub, or if you will, each bar, starting from the left one, begins to scale up only when the previous bar has finished. I can imagine doing this with a scrubbed timeline, but is there an easier way?
  9. I don't have a working example, as I just NPMd 3.0 and grabbed the 149/year club a couple hours ago. I'm used to framer / motion.react. I'm looking for... A rubber duck. Attached is a simple Google searched SVG pitch fork. The best way I can describe my drawing is: flip this 180 and attach another fork on each end. Ok, so. I'm a developer, and i would rather start off the right way vs trial and error. Abstraction is my thing. I wish there was a visual editor, but I can f5 my way to success in NextJS. For the project: think 100 lines, 8k pixels height easy. I'm only using lines, and here are my immediate questions-- Where should I break the lines on the fork? (Handle, edge, 4 prongs? 1 center line and start the prongs when they hit?). Do you need to mask? How would I start the animations of each prong at the same time when the handle is finished? How do I get a consistent draw speed/flow in varying length lines? I'm not drawing a maze, but that's another way to think about it. I'm interested in the approach more than a codepen, but I wouldn't say no to one. Like.. fromTo vs to and all this new stuff.
  10. Hi everyone, I'm facing an issue occasionally, and it's a bit challenging to reproduce reliably in a CodePen due to the complexity of my setup. The issue occurs with dynamic content. Sometimes a part of a GSAP timeline is skipped. Specifically, I notice that the fromTo animations are occasionally stuck in the "to" state, while the rest of the timeline continues as expected. There’s no warning in the console from GSAP, and there are no errors about missing elements. The strange thing is that this mostly happens with WordPress menu items that come in dynamically, which leads me to suspect a timing issue with when the elements are loaded. I tried logging the elements to the console before creating the timeline, and they were all present as a NodeList. Yet, the issue persists. As I mentioned, sometimes it works perfectly fine. I managed to solve this with a slight artificial delay using setTimeout, which seems to allow the timeline to work every time. Interestingly, using GSAP's delay property didn't make a difference. However, using setTimeout feels hacky and unreliable, and I'm hoping there’s a better, more elegant solution. Setup: WordPress website JavaScript: ES6 Modules (using imports/exports) Build Tool: Webpack Has anyone faced similar issues with dynamic content in timelines, especially with WordPress or other dynamically generated content? Are there any best practices in GSAP for handling timing issues with dynamic elements, especially without resorting to setTimeout hacks? I believe this is a broader topic, as I've noticed the same problem in other projects as well. Any advice or insights are greatly appreciated. Thanks in advance!
  11. Leo Barbosa

    Animated Timeline Gsap

    https://codepen.io/leandrobarbosafr/pen/XWvvbWY Timeline animated with GSAP, HTML, CSS and JS
  12. Good day! I was testing some gsap features, and tried to create infinite text swapping animation. But when sometimes I need to smoothly force change text. I am getting bugs. So: I have such method: protected createAnimationTimeline(): void { this._animationTimeline?.kill(); this._animationTimeline = new TimelineMax({ repeat: -1, repeatDelay: this._animationParams.delayBetweenTextsSwap }) .to(this.placeholderText, this._animationParams.duration, { alpha: 0 }) .add(() => this.swapText(), "swapTextLabel") .to(this.placeholderText, this._animationParams.duration, { alpha: 1 }) .play(); } and protected forceSwapText(): void { this._animationTimeline.tweenTo("swapTextLabel"); } _____________________CASE_ONE____________________________ when _animationTimeline moves from this part: .to(this.placeholderText, this._animationParams.duration, { alpha: 0 }) to .add(() => this.swapText(), "swapTextLabel") ___________________________________________________________ - >>>>>>>>>> forceSwapText calls -> everything is ok -> this.swapText() will be inited. But for case ____________________CASE_TWO____________________________ when _animationTimeline moves from this part: .add(() => this.swapText(), "swapTextLabel") to .to(this.placeholderText, this._animationParams.duration, { alpha: 1 }) ___________________________________________________________ - >>>>>>>>>> forceSwapText calls -> moving animations play backwards -> this.swapText() will be not inited. QUESTION: How to make tweenTo("swapTextLabel") always use callback (regardless movement is normal or backwards) ? Thanks a lot, if someone could help me even iwth hint.
  13. Pandastein

    Safari timeline animations issues

    Hi, I have two GSAP timeline animations on the website https://4elements.t-k.dev/. One on the video of featured project section, and one on the panels for the white papers section. It works fine on other browser, but on Safari there is some glitch, flickering, and other issues (The issue in the video: https://drive.google.com/file/d/1b5sgH4aBfAlS6hxYrfc_pMBS9hI1hjM2/view?usp=sharing). Thank you in advance! video-animation.js stack-animation.js
  14. Akash Ranjan

    Draggable Marquee effect

    Hello Guys, I was searching for a draggable marquee effect when I stumbled upon this code pen. This is exactly what I need but I want a marquee effect applied to it which runs in a seamless loop. I tried adding it from my end but it does not work. Please help me Thank You
  15. Sandeep Choudhary

    Add Extra blank scroll in 100Vh Section

    Hi Guys, Hope you are doing good. I am facing issue while using scroll trigger when section is 100Vh or any height section as soon as timeline reach 100 percent or animation completed it start scrolling to next section so in my case if i have to show the slider when animation completed over the box element then its already scroll. If there is any way where can add 2-3 free scroll which will do nothing but stay the section there after timeline complete so any slider or other which will be shown on complete of animation is visible. Any help or suggestion will be very helpful.
  16. Hi all! I know about fromTo, but it`s not working as i expect. I have a code let coinTimeline = gsap.timeline(); coinTimeline.to(movableCoin, { duration: 3, motionPath: { path: bezierToMove, autoRotate: true, align: movableCoin, alignOrigin: [0.5, 0.5] }, repeat: -1, ease: "power1.inOut" }); coinTimeline.fromTo(movableCoin, {opacity: 0}, { duration: 1, opacity: 1 }, 0); And the opacity changing is only in first repeat of animation. Each next time the coin starts from opacity 1. How can I fix that and start it from 0 every time?
  17. Hello everyone, Im new to Gsap, I'm trying to learn it. but right now I'm stuck at creating a vertical animated Timeline. i also applied scrollTrigger but my code is messed up!. Please look at my code. once and correct my mistake. This is what i want to make :- https://youtu.be/qTeqwp7Uvro and this is my code pen:- https://codepen.io/Mohit-Mishra-the-looper/pen/abggwpx?editors=1000 what i want is that. 1. when user scrollDown the height of the ".timeline-inner" will increase. and when the ".timeline-inner" hits the ".dot" of the specific box then the opacity of that's h2 and paragraph become 1
  18. BHAVY J

    Text SVG animations

    Hello GSAP community! I'm trying to animate text and svgs but I don't know why this is not looking great! what I'm trying is to do simillar to gsap home page text animations but not exact same (refer to attached img). so i want to animate ADS word with svgs so each word will go down and svg will come in place with some animation but couldn't figure it out, how do i do it! Please help me out!
  19. Hello everyone. I have an array with text, using position fixed in the upper right corner of the screen and when scrolling to the desired section, I need to show new text, hiding the old one with animation. I did this, but the problem arises that when changing the browser window, everything breaks. Help me with this, please, and how can I optimize this solution? This is a code snippet, because further it is the same (p.s. I don't use useGsap because it breaks animation in production deployment of NExtJS) https://stackblitz.com/edit/stackblitz-starters-h6deec?file=app%2Fcomponent.tsx const TEXTS_FOR_DESKTOP = [ '2024', 'Finance', 'Reward', '2000', '2008', '2015', '2017', '2020', '2023', ] const titleRefs = useRef<(HTMLDivElement | null)[]>([]) const translateToY = -150 useEffect(() => { const mm = gsap.matchMedia(); const splittedText = titleRefs.current.map( (item) => new SplitText(item, { type: "chars" }) ) mm.add( { isTablet: '(min-width: 834px) and (max-width: 1509px)', isDesktop: '(min-width: 1510px)', isExtraSmallMobile: '(max-width: 833px)', }, ctx => { const {isDesktop, isTablet, isExtraSmallMobile} = ctx.conditions! if (isDesktop) { const groups: gsap.DOMTarget[] = gsap.utils.toArray('.trigger') splittedText.forEach((t, i) => { if (i > 0) { gsap.set((t as any).elements[0], { yPercent: 150, position: 'absolute', top: 0, left: 0, width: '100%', }) } }) // 2024-finance gsap.timeline({ scrollTrigger: { invalidateOnRefresh: true, trigger: groups[0], start: 'top top', id: `anim_${0}`, end: '+=260px', // markers: true, scrub: 1, }, }) .to(splittedText[0].chars, { yPercent: -300, ease: 'power2.in', duration: 2.5, stagger: {from: 'end', amount: 0.6}, }) .to( splittedText[1].chars, { yPercent: translateToY, ease: 'power2.in', duration: 2.5, stagger: {from: 'end', amount: 0.6}, }, '<-0.3' ) // finance-reward gsap.timeline({ scrollTrigger: { invalidateOnRefresh: true, trigger: groups[1], start: 'center top', end: '+=500', id: `anim_${1}`, // markers: true, scrub: 1, }, }) .to(splittedText[1].chars, { yPercent: -300, ease: 'power2.in', duration: 2.5, stagger: {from: 'end', amount: 0.6}, }) .to(splittedText[2].chars, { yPercent: translateToY, ease: 'power2.in', duration: 2.5, stagger: {from: 'end', amount: 0.6}, scrollTrigger: { invalidateOnRefresh: true, trigger: groups[1], start: 'center top', end: '+=500', id: `anim_${1}`, // markers: true, scrub: 1, }, }) // reward-2000 gsap.timeline({ scrollTrigger: { invalidateOnRefresh: true, trigger: groups[2], start: '-300 top', end: '+=200', id: `anim_${2}`, // markers: true, scrub: 1, }, }) .to(splittedText[2].chars, { yPercent: -300, ease: 'power2.in', duration: 2.5, stagger: {from: 'end', amount: 0.6}, }) .to(splittedText[3].chars, { yPercent: translateToY, ease: 'power2.in', duration: 2.5, stagger: {from: 'end', amount: 0.6}, scrollTrigger: { invalidateOnRefresh: true, trigger: groups[2], start: '-300 top', end: '+=200', id: `anim_${2}`, // markers: true, scrub: 1, }, }) } } ) }); <div className='fixed right-0 top-0 z-[-1] hidden h-[120px] w-full flex-col gap-[2px] overflow-hidden text-right uppercase 834:flex desktop:h-[200px]'> {TEXTS_FOR_DESKTOP.map((text, index) => ( <div key={index} className={`fluid-text flex items-center justify-end gap-1 font-[500] 834:leading-none`} ref={el => { titleRefs.current[index] = el }} > {text} </div> ))} </div>
  20. tatanka

    How to loop Text slider

    Hello I want to make vertical text slider. I read old post and try to make something but end of lood it shows empty line then restart again. how can i make this slider without empty state gap? blank part:
  21. Hey GSAP Team, I am trying to achieve an animation where on page load, initial sequence of images are played and only after that scroll should be enabled and scroll trigger should take over and play sequence of image on scroll. I am able to achieve the first part of playing image sequence on page load, but stuck on the second part. Can you please nudge me in the right direction 🙏 Thanks. Below is my Vuejs code <script> import { gsap } from 'gsap' export default { data() { return { canvas: null, context: null, images: [], images2: [], frames: { currentFrame: 0 }, frames2: { currentFrame: 64 } } }, mounted() { this.initializeCanvas() this.loadImages() this.initializeAnimation() }, methods: { initializeCanvas() { this.canvas = this.$refs.canvas this.context = this.canvas.getContext('2d') }, getFrameURL(index) { return `http://localhost:5173/demo-${(index) .toString() .padStart(4, '0')}.png` }, loadImages() { for (let i = 0; i < 64; i++) { const img = new Image() img.src = this.getFrameURL(i) this.images.push(img) if ( i === 0) this.render() } for (let i = 64; i < 300; i++) { const img = new Image() img.src = this.getFrameURL(i) this.images2.push(img) } }, initializeAnimation() { const tl = gsap.timeline() tl.to(this.frames, { currentFrame: 64 - 1, snap: 'currentFrame', ease: 'power1.inOut', duration: 2, onUpdate: this.render }) tl.to(this.canvas, { y: 400, duration: 2, onComplete: () => { this.canvas.classList.add('canvas-moved') } }) tl.to(this.frames2, { currentFrame: 299, snap: 'currentFrame', ease: 'power1.inOut', scrollTrigger: { trigger: '.canvas-moved', start: 'top top', end: '+=300%', scrub: 1, markers: true }, onUpdate: this.render2 }) }, render() { this.context.clearRect(0, 0, this.canvas.width, this.canvas.height) const img = this.images[this.frames.currentFrame] const scale = Math.min(this.canvas.width / img.width, this.canvas.height / img.height) this.context.drawImage(img, 0, 0, img.width * scale, img.height * scale) }, render2() { this.context.clearRect(0, 0, this.canvas.width, this.canvas.height) const img = this.images2[this.frames2.currentFrame - 64] console.log(this.frames2.currentFrame) console.log(img) const scale = Math.min(this.canvas.width / img.width, this.canvas.height / img.height) this.context.drawImage(img, 0, 0, img.width * scale, img.height * scale) } } } </script> <template> <div class="canvas-container"> <canvas ref="canvas" width="1560" height="1040" /> </div> </template> <style scoped> .canvas-container { position: relative; width: 100%; height: 100vh; overflow: hidden; z-index: 10; } canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; will-change: opacity; } </style>
  22. Hello, i found some slider using Gsap but i want to modify it with timelines. My goal is when i start scrolling my slide scroll and set rotation to 0 I tried to combine it with timeline but it jumps or anims end when i didnt scroll yet. Without timeline all of them rotates at the same time.
  23. 16067_1494126611

    Center scaling with scrolltrigger

    Hi, I'm working on a website where a large image scales as you scroll. At page load, I want the image to start at 20% scale and be positioned higher on the y-axis so that it's visible in the viewport. While the setup mostly works, I've encountered an issue: when I apply a negative y-position, the scaling no longer happens from the center. https://codepen.io/remcovb/pen/eYwvGqb However, when I remove the negative y-position, the scaling works correctly from the center, but then the image isn't in the viewport anymore. https://codepen.io/remcovb/pen/bGPqoyo Any advice on how to maintain centered scaling while keeping the image in the viewport? Thanks in advance!
  24. kacperkodo

    Updating a Timeline & ScrollTrigger

    Hello, I'm struggling with making my timeline with ScrollTrigger work on resize. It works perfectly every time if I refresh the page, but it doesn't update properly on resize. I have applied both of below: invalidateOnRefresh: true x: () => value(instead of x: value) What am I doing wrong? I am attaching my whole component code (I have just stripped imports). The aim is to simply make it appear as horizontal scroll for the list. I will appreciate any help. Thank you. export function Companies({ data }: { data: Sanity.Company[] }) { const listRef = useRef<HTMLUListElement>(null); const itemsRef = useRef<(HTMLLIElement | null)[]>([]); const tlRef = useRef<gsap.core.Timeline | null>(null); useGSAP( () => { gsap.registerPlugin(ScrollTrigger); const mm = gsap.matchMedia(); mm.add("(min-width: 1024px)", () => { if (!itemsRef.current[0]) { return; } tlRef.current = gsap.timeline({ scrollTrigger: { trigger: listRef.current, start: "bottom bottom", end: `+=3000`, scrub: 2, pin: true, invalidateOnRefresh: true, }, }); tlRef.current.to("li:nth-child(-n + 5)", { y: "0%", stagger: 0.1, duration: 1, }); tlRef.current.to(listRef.current, { invalidateOnRefresh: true, x: () => `-${itemsRef.current[0]?.offsetWidth * itemsRef.current.length - window.innerWidth}`, duration: 4, }); }); }, { scope: listRef } ); return ( <ul className="grid grid-cols-2 gap-x-8 gap-y-24 px-15 pb-52 sm:grid-cols-3 lg:flex lg:w-fit lg:flex-nowrap lg:justify-between lg:gap-0 lg:px-32" ref={listRef} > {data?.map((company, index) => ( <li className={cx(["lg:pr-[7vw]", index < 5 ? "lg:translate-y-full" : ""])} key={index} ref={(el) => { itemsRef.current[index] = el; }} > <Company {...company} /> </li> ))} </ul> ); }
  25. Mitchsitoo

    Hover animations problems

    I've been struggling with this code all day. I've tried everything to get the hover effect to work correctly with a .reverse() but this was the closest I could get to it working correctly. Apparently, it works fine when hovering and unhovering the mouse, but if I repeat these actions, the animation freezes or does weird things. How can I fix this, or is there a better way to do this hover animation? I'd appreciate any help.
×
×
  • Create New...