Search the Community
Showing results for tags 'timeline'.
-
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>
-
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>
- 4 replies
-
- scrolltrigger
- image sequence
-
(and 1 more)
Tagged with:
-
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.
- 8 replies
-
- gsap3
- scrolltrigger
-
(and 1 more)
Tagged with:
-
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!
-
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> ); }
- 2 replies
-
- scrolltrigger
- nextjs
-
(and 2 more)
Tagged with:
-
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.
- 1 reply
-
- gsap
- scrambletext
-
(and 3 more)
Tagged with:
-
Hello Guys, Hope you are doing good, i need some help with timeline issue. iam creating a image slider where iam getting issue regarding starting next time line when current timeline is 50% completed. Eg. when slide first is 50% completed then second slide should be started and so on as slider will be worked infinite Thanks a lot for your help !
-
I want to create animation stack like this section (photo attachment) of the site https://vendredi-society.com/. Does anyone have sample code or something similar? that would help me a lot. Thank you
-
Hello GSAP community ? I had a problem with the animation being quite light I think xD. But I spent hours and couldn't implement it. I am attaching my codepen so you can see my code: https://codepen.io/ProjectDCL/pen/wvbyXQW I'm creating an animation for a modal window to appear to select the language version of the site. My animation works correctly when opening and closing the very first time, but as soon as I try to open/close my modal window again the animation breaks. I think it has to do with this line of code langContainer = $(this).siblings('.lang-container') I use it because on my site there are several places with a language switch and I don't want them all to open at once. I also need that when a modal window is open, if the user clicks anywhere on the site except the modal window itself, then it closes. Perhaps you have ideas on how this can be done? I tried to simply add a reverse timeline when clicking on a $document, but with this approach it will also capture the modal window. Write if you need more information. I will be incredibly grateful for your help!
-
I'm trying to implement a GSAP timeline with Locomotive Scroll beta to pin an element while scrolling in a Next.js component. The code works perfectly in a normal HTML and JS environment, but it's not functioning as expected in Next.js. Here is the minimal demo with normal html environment: https://codesandbox.io/p/sandbox/gsap-timeline-forked-3dqjgv?file=%2Fsrc%2Findex.js%3A8%2C18 Here is the Next Js version: https://codesandbox.io/p/devbox/c4cq6q?file=%2Fpin-element%2Fsrc%2Fapp%2FPinComponent.js%3A28%2C11 I'm new to GSAP and I'm looking for assistance to fix the issue.
- 2 replies
-
- timeline
- scrolltriger
-
(and 1 more)
Tagged with:
-
Greetings! I can't figure out how to implement a random repeatDelay on this simple animation: gsap.timeline({ repeat: -1, repeatDelay: 'random(1, 5)', }) .to('.dot', { ease: 'none', duration: 1, y: '100vh', onComplete() { gsap.set('.dot', { x: 'random(100, 1000)', ease: 'none', }) } }); As you can see, in this simple version of the animation, it's just a dot that starts from random x points at the top and simply falls to the bottom and repeats infinitely. It works fine. But I need the repeatDelay to be random and I thought I could use random for the repeatDelay but I'm obviously doing some wrong...
-
Hello again there, I have Issue about matching the timeline from two different loops. My goal is I want to make the item move a bit whenever the shockwave hit. Currently, I'm match those two manually using a delay. In my real case, there are more items will be showed up, each of the items have their own direction. So, matching it one by one will take much time and sometimes it didn't match with the shockwave. Is there any best practice that I can use? Here's the demo to help you understands my explanation.
-
Hello, I will be much appreciate if someone can help me with this! Since I am not a programmer I have used some help and basic knowledge to achieve the following scrolling effect. https://codepen.io/M-Milde-the-scripter/pen/pomNZeV Basically it start with a image sequence animation, followed by second animation presenting a text with half opacity words, which becomes visible while the user scroll down, and once all the words becomes visible the entire text continue to scroll to reveal the next content. As you can see I am adding some classes on the html element while the user scroll down: - on the header I add .header-active and on the body I add .bg-1 when the first animation ends - and again on the body I add .bg-2 when the second animation ends What I want to achieve is simply to remove those classes in the same order, once the user start to scroll up: - remove the class .bg-2 from the body once the second animation reveals from the t and start to play backwards - remove the class .header-active from the header and .bg-1 from the body, once the firs animation is showing from the top and star to go backwards while the user scrolling up. So the final effect will be when the user scroll back to top the background is again white and the navigation is not visible. on the top example I try with "onReverseComplete", but no success Thank you in advance!
-
I can't use play in timeline, but if not using timeline like gsap.to directly without paused, it can work but I want to pause first then play when I click button, please help me guys?
-
Hello, I'm creating a scroll animation with snapping. Is it possible to set the snap duration based on the remaining animation duration on the timeline? Between Step1 and Step2 I want the snap duration to be max 10; between Step2 and Step3 I want the snap duration to be max 3; between Step3 and end I want the snap duration to be max 6. Is that possible? In my test above, the duration is always round about 2000ms. Thanks Oliver
- 3 replies
-
- scrolltrigger
- snap
-
(and 1 more)
Tagged with:
-
Hi ! Hope you're all doing well, I have a question but not much time to provide a minimal demo, so let me explain my question easily : Let say I have a circle, and I want this circle, when an event fire, to change size, from 0px to 25px, or in reverse from 25px to 0, and when another event fire, from 25px to 100px, and also in reverse from 100px to 25px. I can just create for example two timelines, with a .fromTo(), pass my start and finish values, and use it with the play() and reverse() methods, which works well. But what if I want my circle to change from 25px to 100px ? My first idea was to control the progress(), just by tweening it from let's say : 0.25 to 1. But there is no such thing done smooth (the progress() methods is just a setter). How can I do it with elegance, without creating a third timeline ? Have a nice day ! Thanks !
- 4 replies
-
- progress()
- timeline
-
(and 1 more)
Tagged with:
-
I'm facing a problem with this animation, when I click the add button, it will animate like in the video, but when i click that button again while the previous animation is playing, there will be two animation playing at them same time, that is why when those dots move up to the add button and then later the timelineOpen still playing so it still update the y position making it stay at the same location. I can prenvent it like implement disabled button when timeline is active, but I don’t want it, I want when user click that button whenever they want and the animation if there is one playing it will stop at its position and start another timeline. import { addButton } from "../utils"; import { useDispatch, useSelector } from "react-redux"; import { addButtonClick } from "../redux/action"; import { buttonSelector } from "../redux/selectors"; import { useGSAP } from "@gsap/react"; import gsap from "gsap"; import { useState } from "react"; function Nav() { const dispatch = useDispatch(); const status = useSelector(buttonSelector); const [animationActive, setAnimationActive] = useState(false); const timelineOpen = gsap.timeline({ paused: true, }); const timelineClose = gsap.timeline({ paused: true, }); useGSAP(()=>{ timelineOpen.to("#addButton",{ scale: 0.85, y: -12, rotate: 316, ease: "power1.inOut", duration: 0.3, }) timelineOpen.to("#addButton",{ y: 0, scale: 1, duration: 0.3, }) timelineOpen.to(".First",{ y: 0, scale: 1.3, duration: 0.1, },'-=0.4') timelineOpen.to(".First",{ y: 80, scale: 1, duration: 3.2, ease: "elastic.out(1,0.7)", }, '-=0.3') timelineOpen.fromTo(".Second",{ y: 80, // scaleY: 0, // duration: 1, },{ y: 140, scaleY: 1, duration: 3.2, opacity: 1, ease: "elastic.out(1,0.7)", }, "-=2.7") timelineOpen.fromTo(".Third",{ y: 140, // scaleY: 0, // duration: 1, },{ y: 200, scaleY: 1, duration: 3.2, opacity: 1, ease: "elastic.out(1,0.7)", }, "-=2.9") timelineOpen.fromTo(".Fourth",{ y: 200, // scaleY: 0, // duration: 1, },{ y: 260, scaleY: 1, duration: 3.2, opacity: 1, ease: "elastic.out(1,0.7)", }, "-=2.9") timelineOpen.fromTo(".Fith",{ y: 260, // scaleY: 0, // duration: 1, },{ y: 320, scaleY: 1, duration: 3.2, opacity: 1, ease: "elastic.out(1,0.7)", onComplete: () => { setAnimationActive(false); } }, "-=2.9") timelineClose.to("#addButton",{ scale: 1, rotate: 0, duration: 0.3, }) timelineClose.to(".selector",{ y: 0, duration: 0.7, stagger: 0.1, }) if(status){ timelineOpen.play(); // setAnimationActive(true); }else { timelineClose.play(); // setAnimationActive(true); } },[status]) console.log(animationActive); const handleAddBtn = () => { dispatch(addButtonClick()); } return ( <section className="nav-grid border-r border-[#ececec] flex items-center flex-col row-span-2"> <div className="h-20 flex items-center"> <h4 className="text-xl font-semibold bg-gradient-to-r from-blue-500 to-fuchsia-600 bg-clip-text text-transparent ">TDNote</h4> </div> <div className="notes-container"> <div className="mt-12"> <button // disabled={animationActive} onClick={handleAddBtn} id="addButton" className="z-20 rounded-full bg-black border-none w-14 h-14 outline-none relative cursor-pointer flex items-center justify-center"> <img src={addButton} alt="add button" className="w-7 h-7"/> </button> </div> <div className="note-selector flex justify-center relative z-10 -mt-6"> <div className="selector First bg-[#ffcf7d] z-10 !opacity-100 "></div> <div className="selector other Second bg-[#f0a177] z-[9] "></div> <div className="selector other Third bg-[#b095f6] z-[8]"></div> <div className="selector other Fourth bg-[#55cffa] z-[7]"></div> <div className="selector other Fith bg-[#e6ee96] z-[6]"></div> </div> </div> <svg xmlns="http://www.w3.org/2000/svg" version="1.1"> <defs> <filter id="gooey-effect" xmlns="http://www.w3.org/2000/svg"> <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur"/> <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -9" result="gooey-effect"/> <feComposite in="SourceGraphic" in2="gooey-effect" operator="atop"/> </filter> </defs> </svg> </section> ); } export default Nav; Screen Recording 2024-03-30 at 22.04.51.mov
-
Hello, I hope everyone is well! I'm trying to make an animation where the element goes to position y=95 then waits 3 seconds and returns to position 0 and repeats the animation several times, but I'm not succeeding. I would like guidance to understand what I am doing wrong. Thank you very much in advance. https://codepen.io/daniel-silva-dxp/pen/VwNaZWg
-
Trying to understand timeline.tweenTo and its relation with the position parameter
Guest posted a topic in GSAP
Hello! I'm trying to understand how the position parameter is affected by the "tweenTo" method. From this demo, I tried to make the blue box achieve the same starting point from both forward (0 to 1) and backward (1 to 0) directions (to follow the starting point of the red box), but even after using the "<" position parameter, the blue box doesn't start at the same time when returning (1 to 0). If the timeline is going from 1 to 0 — from my understanding —, the blue box should animate along with the second ".to", as I'm using the "<" parameter. Am I missing something? (sorry if my English is bad) -
Hello! Giving context: I'm coming from Framer Motion and porting a menu animation to GSAP. I'm using the same ease and duration as I used in Framer Motion, but I get this strange delay when the reversed animation is played (when you click "CLOSE" you can feel a delay before going back to "MENU"), if I would guess, it looks like the ease is reversed too, giving this strange animation. If it is the ease, what can I do to use the same ease but in the right direction? (sorry for my bad English)
-
Hello developer, hope you all are doing well. I want my svg to start from the center of the screen, keep animating at the center of the screen and end its animation at the center of the screen. for now, I am using an SVG and keep its height 0 and then it animates to its full height. I am using it for my timeline project but the line starts normally then moves away from the center and speeds up and leaves the screen to the bottom.
- 9 replies
-
- scrolltrigger
- svg
-
(and 1 more)
Tagged with:
-
I got an error here: Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'totalTime') at Timeline.restart (gsap.min.js:10:20564) at tl.clear (confettiCuisine.js:118:10) at Socket.<anonymous> (confettiCuisine.js:145:16) at Emitter.emit (index.mjs:136:20) at Socket.emitEvent (socket.js:498:20) at Socket.onevent (socket.js:485:18) at Socket.onpacket (socket.js:455:22) at Emitter.emit (index.mjs:136:20) at manager.js:204:18 and this is the code ::: function bel(){ const sound = new Audio('/sound/mixkit-fairy-message-notification-861.wav'); sound.addEventListener('canplaythrough', ()=>{ sound.play(); }) } let tl = gsap.timeline( {paused: true, repeat:2}); tl.play = function(){ tl .to(leftBell, { duration: 0.15, css: { scale: 1.2, skewY: "1deg", skewX: "-1deg" }, ease: Power0.easeNone }) .to(rightBell, { duration: 0.15, css: { scale: 1.2, skewY: "1deg", skewX: "-1deg" }, ease: Power0.easeNone }) .to(bodyBell, { x: 0, transformOrigin: "50% 50%" }) .to(bodyBell, { keyframes: [ { x: -3, rotate: 10}, { x: 1.5, rotate: -10}, { x: -1.5, rotate: 6.0 }, { x: 1.5, rotate: -4.4}, { x: -1.5, rotate: 2.2 } ], duration:0.4, ease: Power0.easeNone }); } tl.clear = function (){ this.kill(); this.restart(); } // const submit = () => { function submit() { form.addEventListener('submit', (e) => { e.preventDefault(); socket.emit('message', { content: chatInput.value, userName: Username.value, id: Id.value }); chatInput.value = ""; return false; }); // what i get from the server socket.on('message', (msg) => { if(window.location.pathname !=="/chat"){ displayMessage(msg); bel(); tl.play(); }else{ displayMessage(msg); tl.clear(); } chat.scrollTop = chat.scrollHeight; }) socket.on('load all messages', (data) => { data.forEach(message => { displayMessage(message); }) chat.scrollTop = chat.scrollHeight; }) }
-
Trying to basically "walk" a square across the screen the way you'd tip a heavy box across a room to move it. For it to work, I need to update the transform origin (i.e. rotation point) of the box for each step but since the origin is relative to the original box position, it doesn't quite work. Any thoughts on getting this to work? Currently I'm just using a div but I'm open to SVG solution.
- 1 reply
-
- transformorigin rotate
- transformorigin
-
(and 3 more)
Tagged with:
-
Hellow Everyone! Just need a little help. I only want to show the path that the SVG (Rocket )has covered and not the whole path. as the rocket goes up the path is shown. https://codepen.io/Fawad4real/pen/LYaaOZG
- 4 replies
-
- scrolltrigger
- timeline
-
(and 1 more)
Tagged with: