Jump to content
GreenSock

Leaderboard

Popular Content

Showing content with the highest reputation since 11/30/2020 in all areas

  1. A GSAP tale: One goofy guy’s odyssey from knowing nothing to knowing just enough to confuse himself. (This is crazy long so feel free to jump to the epic conclusion). Greetings fellow GreenSockers. The end of this week marks the one-year anniversary of my first post on the forum so I thought I’d take the opportunity to share my 12-month story and hopefully encourage others to jump into the conversations around here. Maybe you’ll recognize yourself in some of the things I’ve experienced. My quick history in a nutshell Web design and coding is a second career for me. After 15 years of owning and operating a photography studio and processing lab (back in the film days - yup - I’m old), the digital camera came along and changed that industry, which necessitated a new career for me. I shifted to video production, which led to motion graphics and finally to web design. Our little agency now offers all those services. The web design clients never needed anything fancy so JavaScript took a back seat to HTML & CSS only sites for a number of years. JavaScript & GSAP: false starts and other obligations I first discovered GSAP a few years ago, but only tried it briefly. It looked cool, but with the time obligations of field video work and motion graphics jobs, it wasn’t something I could work into the schedule. Besides that, it was JavaScript – too complicated I thought. I knew JavaScript was the third piece of a good web designer’s skillset along with HTML and CSS, but I always convinced myself that I didn’t have the time and the sites we built didn’t need it. JavaScript Books + Classes = Fail I did make a few attempts at reading some JavaScript books and working through some online tutorials, but it just never ‘stuck’. Maybe the examples were too theoretical and dry or they were the wrong books and classes. I really don’t know, but I abandoned the learning process a number of times. Cut and Paste mentality Why did I really need to learn anyway? You can just Google what you need, cut and paste some code and presto – you’ve got some working JavaScript or jQuery. I only understood a small portion of what I was cutting and pasting, but hey… it worked so the problem was solved. That’s how I operated for quite some time. What’s a loop? What’s an array? What’s an object? Who cares? Wait a minute. This is ridiculous. Last spring, I was remodeling our company website and I had all these grand visions about making things move and behave in certain ways. Googling for code just wasn’t cutting it. I suddenly felt stupid. “This is ridiculous!” I thought. I should be able to learn how to write my own code. Oh yeah, I remembered that GreenSock thing I had looked at a few times and abandoned. That might work. Maybe I could actually learn how to use it this time. I become a forum lurker I started lurking in the shadows of the forum. After reading a lot of posts, I saw people asking many types of questions from simple to crazy complicated (at least to me). Two things I noticed were that every effort was made to find an answer (no matter the difficulty level of the question) and not one post was condescending or snarky. That’s quite rare on the ol’ interwebs, isn’t it? Hmmmm…maybe I’m in the right place. Oh boy… time to ask a question of my own One of the great things about learning GSAP is you’ll also pick up a lot of other JavaScript and/or jQuery along the way. I kept reading and practicing with some simple tweens, but now I had a question. Dare I post? I suppose, like many others, I feared looking like an idiot even though the forum members and moderators seemed quite nice and helpful. I do several dumb things every day so you’d think I’d be used to it by now. Oh well, here goes. My first question had to do with the indexOf() a Draggable snap array. Within 30 minutes, Diaco and Rodrigo had posted great answers and neither one called me stupid! Yay – how cool. I get hooked on GSAP and the forum About that same time, I decided our company should discontinue on-site video production and switch to studio only filming. I got tired of lugging loads of video gear in and out of buildings – it’s quite tiring and as I mentioned earlier – I’m old. This freed up some time and I decided to dedicate that time to learning GSAP and maybe, one day, even helping others. It wasn’t too long and I actually knew the answer to a forum question. I posted some information and wow – a little red indicator lit up on my control panel. Someone liked something I wrote. How fun – I’m hooked. Carl makes direct contact I continued to learn and experiment. I posted a few additional questions of my own, but I tried to answer more than I asked. If someone posted a question for which I had no answer, I tried to look it up in the docs and figure it out. Most of the time I was far too slow and Jack, Carl or one of the mods would already have the answer posted before I was done reading the question, but it was an interesting way to learn. I did sneak in a few good answers, which led to a private message from Carl. He thanked me for participating and helping in the forums. I thought it was pretty cool that a super smart guy like Professor Schooff would take the time to do that for little ol’ me. My decision to dedicate time to the platform and forum was reinforced. http://i.imgur.com/hdaB73Y.jpg Blake and I have a conversation I don’t recall if it was a back and forth in a forum post or a private message conversation, but Blake told me something that, of course is obvious, but it stuck with me and is important for all of us to remember. He mentioned that we all enter this learning process knowing nothing. If someone of Blake’s considerable skill level can be humble enough to remember first starting out in code, there may be hope for me after all. I guess if you think about it, there was a time when the simple concept of a variable was brand new to all of us. We’re not born with these abilities. They’re learned and we’re all at different points on the educational path. Never feel stupid for not knowing something. Moderator Promotion Throughout the last year, I’ve continued to learn and study both GSAP and JavaScript. Some of those books I abandoned in the past even make sense now. I’ve tried to be active in the GS community and answer as many forum questions as possible. If I’ve answered a question of yours, I hope you found it somewhat helpful. I’ve cranked out some fun CodePens and finally started a Twitter account to tweet them out. I am nowhere near an expert with GSAP or JavaScript, but I know so much more than I knew a year ago. Apparently I know enough to be entrusted with a forum promotion to Moderator status. I’m honored to be included on such an amazing team. 12 months down – what’s next? My agency duties are still numerous so I can’t dedicate full time to coding, but it remains something to which I’m committed and thoroughly enjoy. I started this 12-month GSAP journey just wanting the ability to write my own code rather than cutting and pasting the work of others. I’m confident I have achieved that, but I still have days when a simple piece of code just won’t coalesce in my brain and that can be frustrating. I guess we all have those days, right? I make several mistakes every day, but that’s o.k. too. I learn a lot more from my screw-ups than I ever do when it all goes right on the first try. I plan to keep learning and getting better and when I get stuck, I’ll be able to get an answer from this amazing community. I’ll continue to give back to the GS community by answering any questions that are within my abilities to do so. The super mods: Jonathan, Blake, Diaco and Rodrigo Thank you to my fellow moderators. You guys rock and have taught me so much. @Jonathan – if there is a browser bug, quirk or special fix that you are not aware of, I’ve yet to read about it. Your knowledge has helped me fix many pieces of code before they even became a problem. Plus, if I ever have a question of top/left vs. x/y, I know who I’ll ask. @Blake – if I could be half as good at coding as you, I’d be a very happy guy. Your work always teaches and inspires me. I don’t think you’re allowed to ever stop posting on the forum or we may all show up on your doorstep and ask questions. @Diaco – your code is always so concise. I deconstruct some of your pens and am astounded by how much you squeeze out of a few lines. If I made some of your pens from scratch, I’d have 20 variables, 5 loops, 12 tweens and 80 lines of code. You do the same with two variables and 4 lines of code. Amazing stuff. @Rodrigo – when searching the forum, I often land on one of your past posts and learn a lot. Your knowledge is vast and I wish you had more time to post around here. Your ninja skills are incredibly strong. Our superhero leaders @Carl – I’ve participated in several online forums ranging from graphic design to 3D to video production, but the GreenSock forum is the best and a big part of that is you. You not only provide great answers, but you do it in clever ways with just the right amount of humor thrown in here and there. The collection of videos you’ve made is invaluable and should be mandatory viewing for anyone interested in GSAP. I’ve seen you monitoring the forums at all hours of the day and even on weekends. When you get any sleep I’ll never know, but I thank you for your dedication and sharing your knowledge. @Jack – how you had the vision to start GreenSock and write the first version of the animation platform I can only imagine. I’m glad you did because GSAP is such an amazing collection of tools. The friendliness of the community is definitely following your lead. I don’t understand a lot of what you talk about sometimes, but I know enough to be amazed by your brilliance and talent. You call yourself just a guy who geeks out about code, but you’re more than that. You’re a smart and generous innovator who’s created a special brand and place on the web. I think I can safely speak for the community when I say we all appreciate the time and effort you put into helping us make beautiful and high-performance animations. Thank you sir. The epic conclusion. Well… maybe just a regular conclusion. If you didn’t read the whole post, I don’t blame you. It’s ridiculously long and I’m just some guy you don’t know so I’ll wrap it up with this bit of advice. Whether you’re a genius or feel like an idiot, it doesn’t matter. Try to learn one new thing each day and before you know it, a year will have passed and all those little bits will add up to new skills and abilities. If you’ve never posted on the forum, please jump in and participate. The more voices we have around here, the more we all benefit. If you need an answer, please don’t be afraid to ask a question. Believe me, I’m just some goofy guy in front of a computer. If I can learn this stuff, so can you. As I begin my second year in GreenSockLand, I’m looking forward to learning more, seeing everyone’s work and answering as many of your questions as I can. This is an amazing community and I encourage anyone reading this to set up an account and get involved. My best to all of my fellow GreenSockers. See you around the forums. Edit and Update (July 2020): I just made it to five years of hanging around the forum and you can read the continuation of my journey here. motiontricks.com Finally, without further ado, I introduce you to motiontricks.com - Craig (PointC) PS I made a little CodePen to commemorate my one-year forum anniversary. It’s how I felt before and after discovering the power of GSAP. Enjoy.
    19 points
  2. Welcome to the GreenSock forums! Glad you’re here. It’s a wonderful place to learn and get your questions answered. What topics can I post about here? We love answering questions that are directly related to GreenSock tools. API questions, bug reports, or if you’re wondering why GSAP behaves a certain way - those types of posts are welcome around here. What topics should be avoided? As much as we love solving problems, the following types of questions are beyond the scope of what we generally provide here for free: Logic issues. JavaScript and application logic, CSS setup, and generic troubleshooting that isn’t directly related to GreenSock tools. Third party tools. Frameworks (React, Angular), other JavaScript libraries (LocomotiveScroll, Barba), build tools, etc. We’re happy to help with the GSAP part of things if you strip out as much irrelevant code as possible and provide a minimal demo. “How do I do this cool effect I saw on a trendy website?” Someone here may point you in the right direction but please don't expect a full tutorial on how to create and effect you saw on a slick web site. Where else can I go for help? If your question is primarily about another tool, try looking for a forum or GitHub repository about that tool. If it’s a general programming-related question, try StackOverflow. Want feedback about your working code? We’d be glad to take a peek at GSAP-specific code but for more general topics (like performance or application logic) we’d suggest something like CodeReview. Read first Please read Getting Started with GSAP, common GSAP mistakes (maybe also common ScrollTrigger mistakes), as well as the GSAP docs before asking your question. Often you’ll get your question answered just by doing that! Make a minimal demo This helps provide context and gives us a rough idea of what you’re trying to accomplish. It's WAY better than trying to dig into a live website with lots of other things going on, or looking at a small excerpt of code without much context. Pro tip: It's often easier to create a minimal demo from scratch rather than stripping out irrelevant things from your original project. You will GREATLY increase your chances of getting a prompt answer if you create a minimal demo. After you've posted a demo to our forums, please click the "Fork" button on CodePen before making future changes so that context is not lost for future readers of the forum. Be courteous We try to treat people the way we’d want to be treated around here. Please do the same. Also keep in mind that the people answering your post are doing so for free! Most of our regular contributors gain nothing from helping you except the satisfaction of doing so. Please give them your gratitude and respect. Ask away! We’re eager to help, so make a minimal demo and ask your question! We’ll do our best to answer it promptly. Pay it forward - help someone else The best way to learn is to teach someone. You’d be surprised how much you grow when you try answering some questions here! We are so grateful for the group of volunteers dedicated to helping others in these forums. It’s quite satisfying to come alongside a fellow developer who is struggling and deliver a clever solution to their issue. Become a contributor! You do NOT need to be an expert. Anyone...and we do mean anyone...is welcome here.
    18 points
  3. Struggling with .from() tweens in React 18? This is due to React's new 'Strict mode' - this forum thread will help you get back on track. React is a hugely popular library choice, and as evidenced by many of the sites in our showcase - React and GSAP can be a powerful combination. However, utilizing GSAP in React requires a different way of thinking than a vanilla JS project. We've written this guide to help you get started using GSAP within a React project. This is not a tutorial, so feel free to dip in and out as you learn. Think of it as a collection of recommended techniques and best practices to use in your projects. Why GSAP? Animating with GSAP gives you unprecedented levels of control and flexibility. You can reach for GSAP to animate everything — from simple DOM transitions to SVG, three.js, canvas or WebGL — your imagination is the limit. More importantly, you can rely on us. We obsess about performance, optimizations and browser compatibility so that you can focus on the fun stuff. We've actively maintained and refined our tools for over a decade and there are no plans to stop. Lastly, if you ever get stuck, our friendly forum community is there to help. Going forward we will assume a basic understanding of GSAP and React. If you're just getting going with React, this tutorial from the React team is a great place to start. Need a GSAP refresher? Take a break and read about tweens and timelines. We’ll be here when you get back. Feeling confident? Skip straight to part 2 - GSAP + React, advanced animation techniques. Quick Links Getting set up Targeting a DOM element for animation Creating our first animation Targeting descendant elements Creating a timeline Controlling when React runs our animation with useEffect Reacting to changes in state Animating on interaction Avoiding flash of unstyled content (FOUC) Cleaning up Online Playgrounds Get started quickly by forking one of these starter templates: CodePen CodeSandbox CodeSandbox + Bonus Plugins Create a new React App If you prefer to work locally, Create React App provides a comfortable setup for experimenting with React and GSAP. To create a project, run: npx create-react-app gsap-app cd gsap-app npm start Once the project is set up we can install GSAP through npm, npm i gsap npm start then import it into our app. import React from "react"; import { gsap } from "gsap"; export default function App() { return ( <div className="app"> <div className="box">Hello</div> </div> ); } More detailed information about getting started with React Additional GSAP installation documentation Targeting elements In order to animate using GSAP we need access to the element in the DOM. Refs provide a way for us to interact with and store references to DOM nodes in a React component. const boxRef = useRef(); return <div className="box" ref={boxRef}>Hello</div>; Read more about refs in the React docs Creating our first animation GSAP updates inline style properties, so it’s important to make sure the DOM has been rendered before trying to animate anything. If we ask GSAP to animate an element that hasn’t been rendered, we’ll get this warning in the console. GSAP target not found. In order to avoid targeting a null element, we can use the useEffect hook. This hook tells React that our component needs to do something after rendering. function App() { // store a reference to the box div const boxRef = useRef(); // wait until DOM has been rendered useEffect(() => { gsap.to(boxRef.current, { rotation: "+=360" }); }); // DOM to render return <div className="box" ref={boxRef}>Hello</div>; } In this example, React will first render the box element to the DOM, then GSAP will rotate the box 360deg. See the Pen React & GSAP Starter Template by GreenSock (@GreenSock) on CodePen. Targeting descendant elements gsap.utils.selector() Creating a ref for each and every element we want to animate can add a lot of noise to our code. We can avoid this by making use of GSAP’s selector utility to easily select descendant elements. const el = useRef(); const q = gsap.utils.selector(el); useEffect(() => { // Target ALL descendants with the class of .box gsap.to(q(".box"), { x: 100 }); }, []); See the Pen gsap.utils.selector() by GreenSock (@GreenSock) on CodePen. Forwarding refs gsap.utils.selector() will target all descendants in the component tree. Within a component based system, you may need more granular control over the elements you're targeting. You can use ref forwarding to get access to specific nested elements. See the Pen Forwarding refs by GreenSock (@GreenSock) on CodePen. Creating and controlling timelines Up until now we've just used refs to store references to DOM elements, but they're not just for elements. Refs exists outside of the render loop - so they can be used to store any value that you would like to persist for the life of a component. If you're coming from class based components, this should be familiar to you as it’s essentially the same as using ‘this’. In order to avoid creating a new timeline on every render, it's important to create the timeline inside an effect and store it in a ref. function App() { const el = useRef(); const q = gsap.utils.selector(el); const tl = useRef(); useEffect(() => { tl.current = gsap.timeline() .to(q(".box"), { rotate: 360 }) .to(q(".circle"), { x: 100 }); }, []); return ( <div className="app" ref={el}> <Box>Box</Box> <Circle>Circle</Circle> </div> ); } This will also allow us to access the timeline in a different effect and toggle the timeline direction. See the Pen React Tutorial 2f by GreenSock (@GreenSock) on CodePen. Controlling when React runs our animation. By default useEffect runs both after the first render and after every update. So every time our component’s state changes, it will cause a re-render, which will run our effect again. We can control when useEffect should run by passing in an array of dependencies. To only run once after the first render, we pass in an empty array. // only runs after first render useEffect(() => { gsap.to(q(".box-1"), { rotation: "+=360" }); }, []); // runs after first render and every time `someProp` changes useEffect(() => { gsap.to(q(".box-2"), { rotation: "+=360" }); }, [someProp]); // runs after every render useEffect(() => { gsap.to(q(".box-3"), { rotation: "+=360" }); }); See the Pen React Tutorial 1b by GreenSock (@GreenSock) on CodePen. Reacting to changes in state Now that we know how to control when an effect fires, we can use this pattern to react to changes in our component. This is especially useful when passing down props. function Box({ children, endX}) { const boxRef = useRef(); // run when `endX` changes useEffect(() => { gsap.to(boxRef.current, { x: endX }); }, [endX]); return ( <div className="box" ref={boxRef}>{children}</div> ); } See the Pen React Tutorial 1c by GreenSock (@GreenSock) on CodePen. Animating on interaction Interaction is one of the most exciting things about animating on the web! In order to hook into user interactions like hover, we can use callbacks. const onEnter = ({ currentTarget }) => { gsap.to(currentTarget, { backgroundColor: "#e77614" }); }; const onLeave = ({ currentTarget }) => { gsap.to(currentTarget, { backgroundColor: "#28a92b" }); }; return ( <div className="box" onMouseEnter={onEnter} onMouseLeave={onLeave}> Hover Me </div> ); See the Pen React Tutorial 1d by GreenSock (@GreenSock) on CodePen. Avoiding flash of unstyled content (FOUC) As useEffect fires after the DOM has been painted, when fading in elements you may notice an undesired flash of unstyled content. In order to avoid the flash, we can replace useEffect with useLayoutEffect. useLayoutEffect functions exactly the same as useEffect, but runs before the DOM has been painted. See the Pen Avoiding FOUC with useLayoutEffect() by GreenSock (@GreenSock) on CodePen. useLayoutEffect is especially useful when you need to make DOM measurements, so we highly recommend it when using our ScrollTrigger and FLIP plugins. More information about useEffect vs useLayoutEffect. Cleaning Up It’s a good idea to return a cleanup function in your effects to kill off any running animations and anything else that could cause a memory leak, like an event listener. This is particularly important if an animation runs for a really long time, makes use of ScrollTrigger, or changes the state in a component. useEffect(() => { const animation1 = gsap.to(".box1", { rotation: "+=360" }); const animation2 = gsap.to(".box2", { scrollTrigger: { ... } }); const onMove = () => { ... }; window.addEventListener("pointermove", onMove); // cleanup function will be called when component is removed return () => { animation1.kill(); animation2.scrollTrigger.kill(); window.removeEventListener("pointermove", onMove); }; }, []); We hope this article was helpful - If you have any feedback please leave us a comment below so we can smooth out the learning curve for future animators! Feeling confident and want to learn more? Check out our follow up article - GSAP + React, advanced animation techniques.
    13 points
  4. I know this thread is now over a month old, but I wanted to share a fork of Zach's pen. I made a 6-sided die from the cube. To simplify/clarify, the 3d rotations are moved out of the CSS. Hopefully this demo is useful to someone... https://codepen.io/creativeocean/pen/qBRbNwa
    12 points
  5. Are you working with React and looking to really advance your GSAP animation skills? You're in the right place. This guide contains advanced techniques and some handy tips from expert animators in our community. This is not a tutorial, so feel free to dip in and out as you learn. Think of it as a collection of recommended techniques and best practices to use in your projects. Why GSAP? Animating with GSAP gives you unprecedented levels of control and flexibility. You can reach for GSAP to animate everything — from simple DOM transitions to SVG, three.js, canvas or WebGL — your imagination is the limit. More importantly, you can rely on us. We obsess about performance, optimizations and browser compatibility so that you can focus on the fun stuff. We've actively maintained and refined our tools for over a decade and there are no plans to stop. Lastly, if you ever get stuck, our friendly forum community is there to help. Going forward we will assume a comfortable understanding of both GSAP and React. If you're starting out we highly recommend reading our foundational article first - First Steps & Handy Techniques.. Quick Links Component Communication Passing down a timeline prop Passing down callback to build a timeline React Context Imperative Communication Creating Reusable Animations registerEffect() Exit Animations Custom Hooks useSelector useArrayRef useStateRef useIsomorphicLayoutEffect Online Playgrounds Get started quickly by forking one of these starter templates: CodePen CodeSandbox CodeSandbox + Bonus Plugins Component Communication In the last article, we covered creating our first animation, and how to create and control timelines within a React component. But there are times where you may need to share a timeline across multiple components or construct animations from elements that exist in different components. In order to achieve this, we need a way to communicate between our components. There are 2 basic approaches to this. a parent component can send down props, e.g. a timeline a parent component can pass down a callback for the child to call, which could add animations to a timeline. Passing down a timeline prop Note that we are using useState instead of useRef with the timeline. This is to ensure the timeline will be available when the child renders for the first time. function Box({ children, timeline, index }) { const el = useRef(); // add 'left 100px' animation to timeline useEffect(() => { timeline.to(el.current, { x: -100 }, index * 0.1); }, [timeline]); return <div className="box" ref={el}>{children}</div>; } function Circle({ children, timeline, index, rotation }) { const el = useRef(); // add 'right 100px, rotate 360deg' animation to timeline useEffect(() => { timeline.to(el.current, { rotate: rotation, x: 100 }, index * 0.1); }, [timeline, rotation]); return <div className="circle" ref={el}>{children}</div>; } function App() { const [tl, setTl] = useState(() => gsap.timeline()); return ( <div className="app"> <Box timeline={tl} index={0}>Box</Box> <Circle timeline={tl} rotation={360} index={1}>Circle</Circle> </div> ); } See the Pen React Tutorial 3a by GreenSock (@GreenSock) on CodePen. Passing down a callback to build a timeline function Box({ children, addAnimation, index }) { const el = useRef(); // return a 'left 100px' tween useEffect(() => { const animation = gsap.to(el.current, { x: -100 }); addAnimation(animation, index); return () => animation.progress(0).kill(); }, [addAnimation, index]); return <div className="box" ref={el}>{children}</div>; } function Circle({ children, addAnimation, index, rotation }) { const el = useRef(); // return a 'right 100px, rotate 360deg' tween useEffect(() => { const animation = gsap.to(el.current, { rotate: rotation, x: 100 }); addAnimation(animation, index); return () => animation.progress(0).kill(); }, [addAnimation, index, rotation]); return <div className="circle" ref={el}>{children}</div>; } function App() { // define a timeline const [tl, setTl] = useState(() => gsap.timeline()); // pass a callback to child elements, this will add animations to the timeline const addAnimation = useCallback((animation, index) => { tl.add(animation, index * 0.1); }, [tl]); return ( <div className="app"> <Box addAnimation={addAnimation} index={0}>Box</Box> <Circle addAnimation={addAnimation} index={1} rotation="360">Circle</Circle> </div> ); } See the Pen Passing down a callback to build a timeline. by GreenSock (@GreenSock) on CodePen. React Context Passing down props or callbacks might not be ideal for every situation. The component you're trying to communicate with may be deeply nested inside other components, or in a completely different tree. For situations like this, you can use React's Context. Whatever value your Context Provider provides will be available to any child component that uses the useContext hook. const SelectedContext = createContext(); function Box({ children, id }) { const el = useRef(); const selected = useContext(SelectedContext); useEffect(() => { gsap.to(el.current, { // animate x by 200 if the box ID matches the selected context value x: selected === id ? 200 : 0 }); }, [selected, id]); return <div className="box" ref={el}>{children}</div>; } function App() { // Any component can read the value passed to the provider, no matter how deeply nested. // In this example, we're passing "2" as the current value. return ( <SelectedContext.Provider value="2"> <Box id="1">Box 1</Box> <Box id="2">Box 2</Box> <Box id="3">Box 3</Box> </SelectedContext.Provider> ); } See the Pen React Tutorial 3c by GreenSock (@GreenSock) on CodePen. Imperative Communication Passing around props or using Context works well in most situations, but using those mechanisms cause re-renders, which could hurt performance if you're constantly changing a value, like something based on the mouse position. To bypass React’s rendering phase, we can use the useImperativeHandle hook, and create an API for our component. const Circle = forwardRef((props, ref) => { const el = useRef(); useImperativeHandle(ref, () => { // return our API return { moveTo(x, y) { gsap.to(el.current, { x, y }); } }; }, []); return <div className="circle" ref={el}></div>; }); Whatever value the imperative hook returns will be forwarded as a ref function App() { const circleRef = useRef(); useEffect(() => { // doesn't trigger a render! circleRef.current.moveTo(300, 100); }, []); return ( <div className="app"> <Circle ref={circleRef} /> </div> ); } See the Pen React Tutorial 3d by GreenSock (@GreenSock) on CodePen. Creating reusable animations Creating reusable animations is a great way to keep your code clean while reducing your app’s file size. The simplest way to do this would be to call a function to create an animation. function fadeIn(target, vars) { return gsap.from(target, { opacity: 0, ...vars }); } function App() { const box = useRef(); useLayoutEffect(() => { const animation = fadeIn(box.current, { x: 100 }); }, []); return <div className="box" ref={box}>Hello</div>; } For a more declarative approach, you can create a component to handle the animation. function FadeIn({ children, vars }) { const el = useRef(); useLayoutEffect(() => { gsap.from(el.current.children, { opacity: 0, ...vars }); }, []); return <span ref={el}>{children}</span>; } function App() { return ( <FadeIn vars={{ x: 100 }}> <div className="box">Box</div> </FadeIn> ); } See the Pen React Reusable 1 by GreenSock (@GreenSock) on CodePen. If you want to use a React Fragment or animate a function component, you should pass in a ref for the target(s). Using gsap.effects GSAP provides a way to create reusable animations with registerEffect() function GsapEffect({ children, targetRef, effect, vars }) { useLayoutEffect(() => { if (gsap.effects[effect]) { gsap.effects[effect](targetRef.current, vars); } }, [effect]); return <>{children}</>; } function App() { const box = useRef(); return ( <GsapEffect targetRef={box} effect="spin"> <Box ref={box}>Hello</Box> </GsapEffect> ); } See the Pen React Reusable 6 by GreenSock (@GreenSock) on CodePen. Exit animations To animate elements that are exiting the DOM, we need to delay when React removes the element. We can do this by changing the component’s state after the animation has completed. function App() { const boxRef = useRef(); const [active, setActive] = useState(true); const remove = () => { gsap.to(boxRef.current, { opacity: 0, onComplete: () => setActive(false) }); }; return ( <div> <button onClick={remove}>Remove</button> { active ? <div ref={boxRef}>Box</div> : null } </div> ); } See the Pen React fade out 1 by GreenSock (@GreenSock) on CodePen. The same approach can be used when rendering elements from an array. function App() { const [items, setItems] = useState([ { id: 0 }, { id: 1 }, { id: 2 } ]); const removeItem = (value) => { setItems(prev => prev.filter(item => item !== value)); } const remove = (item, target) => { gsap.to(target, { opacity: 0, onComplete: () => removeItem(item) }); }; return ( <div> {items.map((item) => ( <div key={item.id} onClick={(e) => remove(item, e.currentTarget)}> Click Me </div> ))} </div> ); } See the Pen React fade out 2 by GreenSock (@GreenSock) on CodePen. However - you may have noticed the layout shift - this is typical of exit animations. The Flip plugin can be used to smooth this out. In this demo, we’re tapping into Flip’s onEnter and onLeave to define our animations. To trigger onLeave, we have to set display: none on the elements we want to animate out. See the Pen React Flip 2 by GreenSock (@GreenSock) on CodePen. Custom Hooks If you find yourself reusing the same logic over and over again, there’s a good chance you can extract that logic into a custom hook. Building your own Hooks lets you extract component logic into reusable functions. Let's take another look at registerEffect() with a custom hook function useGsapEffect(target, effect, vars) { const [animation, setAnimation] = useState(); useLayoutEffect(() => { setAnimation(gsap.effects[effect](target.current, vars)); }, [effect]); return animation; } function App() { const box = useRef(); const animation = useGsapEffect(box, "spin"); return <Box ref={box}>Hello</Box>; } See the Pen React Reusable 7 by GreenSock (@GreenSock) on CodePen. Here are some custom hooks we've written that we think you may find useful: useSelector Memoises GSAP’s selector utility. see demo on codepen function useSelector() { const ref = useRef(); const q = useMemo(() => gsap.utils.selector(ref), [ref]); return [q, ref]; } Usage: function App() { const [q, ref] = useSelector(); useEffect(() => { gsap.to(q(".box"), { x: 200 }); }, []); return ( <div ref={ref}> <div className="box">Hello</div> </div> ); } useArrayRef Adds refs to an array. see demo on codepen function useArrayRef() { const refs = useRef([]); refs.current = []; return [refs, (ref) => ref && refs.current.push(ref)]; } Usage: function App() { const [refs, setRef] = useArrayRef(); useEffect(() => { gsap.to(refs.current, { x: 200 }); }, []); return ( <div> <div className="box" ref={setRef}>Box 1</div> <div className="box" ref={setRef}>Box 2</div> <div className="box" ref={setRef}>Box 3</div> </div> ); } useStateRef This hook helps solve the problem of accessing stale values in your callbacks. It works exactly like useState, but returns a third value, a ref with the current state. see demo on codepen function useStateRef(defaultValue) { const [state, setState] = useState(defaultValue); const ref = useRef(state); const dispatch = useCallback((value) => { ref.current = typeof value === "function" ? value(ref.current) : value; setState(ref.current); }, []); return [state, dispatch, ref]; } Usage: const [count, setCount, countRef] = useStateRef(5); const [gsapCount, setGsapCount] = useState(0); useEffect(() => { gsap.to(box.current, { x: 200, repeat: -1, onRepeat: () => setGsapCount(countRef.current) }); }, []); useIsomorphicLayoutEffect You might see a warning if you use server-side rendering (SSR) with useLayoutEffect. You can get around this by conditionally using useEffect during server rendering. This hook will return useLayoutEffect when the code is running in the browser, and useEffect on the server. caveat: Any "from" state that doesn't match the server-side rendered HTML/CSS content will still suffer from a flash of unstyled content while the JavaScript is being parsed, run and hydrated. read more about useLayoutEffect and server rendering see demo on codepen const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect; Usage: function App() { const box = useRef(); useIsomorphicLayoutEffect(() => { gsap.from(box.current, { opacity: 0 }); }, []); return ( <div> <div className="box" ref={box}>Hello</div> </div> ); } If there is anything you'd like to see included in this article, or if you have any feedback, please leave a comment below so that we can smooth out the learning curve for future animators. Good luck with your React projects and happy tweening!
    11 points
  6. Highlights: ScrollSmoother plugin for delicious, buttery-smooth scrolling that leverages native scroll. 💚 Observer plugin that greatly simplifies setup for reacting to various events across devices. gsap.quickTo() for frequent redirection to new values like mouse followers ScrollTrigger.normalizeScroll() solves a bunch of scroll-related annoyances across devices and browsers. "*=" and "/=" relative prefixes - multiply or divide the current value. Introducing ScrollSmoother.🥳 A shiny new plugin, exclusively for Club GreenSock members! ScrollSmoother makes it simple to add a buttery smooth vertical scrolling effect to your ScrollTrigger pages. Under the hood, ScrollSmoother leverages native scrolling which allows it to sidestep many of the accessibility annoyances that plague smooth-scrolling sites. No fake scrollbars, and no messing with pointer or touch functionality. See the Pen ScrollSmoother by GreenSock (@GreenSock) on CodePen. ScrollSmoother.create({ content: "#smooth-content", wrapper: "#smooth-wrapper", smooth: 1, // how long (in seconds) it takes to "catch up" to the native scroll position effects: true, // looks for data-speed and data-lag attributes on elements normalizeScroll: true, // prevents address bar from showing/hiding on most devices, solves various other browser inconsistencies ignoreMobileResize: true // skips ScrollTrigger.refresh() on mobile resizes from address bar showing/hiding }); Effects... ScrollSmoother will integrate seamlessly with all your scroll-triggered animations. but we've also added some bonus ScrollSmoother effects. ✨ speed - Great for parallax effects! It adjusts the speed at which an element moves vertically while scrolling through the viewport. A speed of 1 is normal speed, 2 is double speed, etc. lag - Add some lag* to gently flow elements behind the scroll before they ease back to their natural scroll position. * no seriously, trust us. It's the good kind of lag. <div data-speed="0.5"></div> <!-- half-speed of scroll --> <div data-speed="2"></div> <!-- double-speed of scroll --> <div data-speed="1"></div> <!-- normal speed of scroll --> <div data-lag="0.5"></div> <!-- takes 0.5 seconds to "catch up" --> <div data-lag="0.8"></div> <!-- takes 0.8 seconds to "catch up" --> Read the docs for all the juicy details, or pull up a seat and watch this short explainer video. Observer The brand new 3.5kb Observer plugin offers a super-flexible, unified way to sense meaningful events across all (touch/mouse/pointer) devices without wrestling with all the implementation details. Perhaps you want to respond to "scroll-like" user behavior which could be a mouse wheel spin, finger swipe on a touch device, a scrollbar drag, or a pointer press & drag...and of course you need directional data and velocity. No problem! Tell Observer which event types to watch (wheel, touch, pointer, and/or scroll) and it will collect delta values over the course of each requestAnimationFrame tick (debounced for performance by default) and automatically determine the biggest delta and then trigger the appropriate callback(s) like onUp, onDown, onDrag, etc. Look how easy it is to trigger next()/previous() functions based on when the user swipes up/down or uses their mouse wheel: Observer.create({ target: window, // can be any element (selector text is fine) type: "wheel,touch", // comma-delimited list of what to listen for ("wheel,touch,scroll,pointer") onUp: () => previous(), onDown: () => next(), }); Demo Notice there's no actual scrolling in the demo below but you can use your mouse wheel (or swipe on touch devices) to initiate movement so it "feels" like a scroll: Since ScrollTrigger leverages Observer internally for normalizeScroll(), we exposed it via ScrollTrigger.observe() so you don't have to load an extra file if you're already using ScrollTrigger. Excited? Why don't you observe this video or check out the docs (see what we did there?). gsap.quickTo() If you find yourself calling gsap.to() many times on the same numeric property of the same target, like in a "mousemove" event, you can boost performance by creating a quickTo() function instead. Think of a quickTo() like an optimized function tied to one particular numeric property, where it directly pipes a new number to it. Example let xTo = gsap.quickTo("#id", "x", {duration: 0.4, ease: "power3"}), yTo = gsap.quickTo("#id", "y", {duration: 0.4, ease: "power3"}); document.querySelector("#container").addEventListener("mousemove", e => { xTo(e.pageX); yTo(e.pageY); }); Mouse Follower Demo See the Pen gsap.quickTo() mouse follower by GreenSock ( @GreenSock) on CodePen. ScrollTrigger.normalizeScroll() and ignoreMobileResize Have you ever run into these problems?: Address bar on mobile browsers shows/hides and resizes the viewport, causing jumps When scrolling fast, a pinned element seems to shoot past for a brief moment and then jump to the correct pinned position (multi-thread synchronization issues) iOS jitter Overscroll behavior that seems impossible to prevent on iOS Inconsistent momentum scrolling across devices The powerful new normalizeScroll() functionality intercepts native browser scroll behavior and handles it on the JavaScript thread instead which solves the problems mentioned above on most devices (iOS Phones in portrait orientation still show/hide the address bar). To enable it, simply: ScrollTrigger.normalizeScroll(true); To prevent ScrollTrigger.refresh() from running (and recalculating start/end positions) when a mobile browser shows/hides its address bar, you can now do: ScrollTrigger.config({ ignoreMobileResize: true }); So easy! Read more in the docs. New "*=" and "/=" relative prefixes You've always been able to add or subtract from the current value, like: gsap.to(".box", { x: "+=100", // 100 more than the current value y: "-=100", // 100 less than the current value }); ...and now you can multiply or divide accordingly: gsap.to(".box", { x: "*=2", // double the current value y: "/=2", // halve the current value }); And more... GSAP 3.10 also delivers various bug fixes, so we'd highly recommend installing the latest version today. There are many ways to get GSAP - see the Installation page for all the options (download, NPM, zip, Github, etc.). Resources Full release notes on Github Full documentation Getting started with GSAP Learning resources Community forums Happy tweening!
    10 points
  7. Hey everyone! I've been working on a fun demo project called TweenPages to show how I do complex page transitions with GSAP in Next.js. I haven't shared it yet with anyone publicly until now. Would love to get some early feedback. Especially on the docs where I go into detail on the code side of things. Am I doing it right? Am I doing it wrong? Are there things I can improve? Fun! - https://tweenpages.vercel.app/ Docs - https://tweenpages.vercel.app/docs Code - https://github.com/johnpolacek/TweenPages Hope the project helps anyone who want to do GSAP animations like these on Next.js.
    10 points
  8. OMG! I was about to get fired, ScrollSmoother saved my life
    10 points
  9. Hey, I created a simple example based on this CodePen from the GreenSock collection (I assume that this is what you're after). Now for some reason in Codesandbox this didn't worked so I had to create a repo and publish the sample in the corresponding GitHub page. This is the repo url: https://github.com/rhernandog/gsap-flip-react Here is the meat of the code: https://github.com/rhernandog/gsap-flip-react/blob/master/src/App.js Here is the live sample: https://rhernandog.github.io/gsap-flip-react/ Based on your initial post in the thread, I take that you want to remove the elements from the DOM when they're animated out and mount them back, once they're animated in. Unfortunately, for work reasons I don't have enough time to add such feature to this sample, but this should be a good starting point for it and hopefully it will help you. When I have more time in the future I hope to be able to improve this sample. Happy Tweening!!!
    10 points
  10. Just to throw my two cents out there - some CodePen accounts to bookmark and/or follow. Talented coders that feature a ton of GSAP: Cassie Evans: https://codepen.io/cassie-codes Blake Bowen: https://codepen.io/osublake Carl Schooff: https://codepen.io/snorkltv Pete Barr: https://codepen.io/petebarr Steve Gardner: https://codepen.io/ste-vg Ryan Mulligan: https://codepen.io/hexagoncircle Tom Miller: https://codepen.io/creativeocean Chris Gannon: https://codepen.io/chrisgannon Darin Senneff: https://codepen.io/dsenneff Craig Roblewsky: https://codepen.io/PointC/ (this guy is awesome 🤣) It may not be exactly what you need, but there should some good inspiration in those accounts. Happy tweening.
    9 points
  11. Not exactly like the example button - a lot less liquidy, but fun nonetheless! https://codepen.io/cassie-codes/pen/15d1e3d339a64bbed746895dff4990b9?editors=0010
    9 points
  12. In case anyone else comes across this like I did, having trouble with GSAP animating from one clip-path to another: make sure both clip-paths are using the same units, including any zero values. For example, trying to animate from this: clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); to this: clip-path: polygon(-100% 0, -100% 0, -100% 100%, -100% 100%) wasn't working, but when I changed the zero values to percentages, it worked perfectly. // From clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%) // To clip-path: polygon(-100% 0%, -100% 0%, -100% 100%, -100% 100%)
    9 points
  13. See the Pen box by GreenSock (@GreenSock) on CodePen. Highlights: Flip Plugin is no longer for members-only! - consider it an early Christmas present from us to you. 💚 CustomEase is now in the public downloads as well (and on the CDN)! 'Tis the season to be jolly. 🎁 Brand new Keyframe options that can drastically reduce the amount of code you must write. If you're used to CSS keyframes, you'll love this. Flip Plugin got a major overhaul and new features including batch() for complex scenarios. FLIP animations for everyone! 🥳 Flip plugin can give you some serious animation superpowers once you learn to think in terms of "FLIP" ("First", "Last", "Invert", "Play"). Here's a demo that explains the technique: See the Pen How GSAP&#39;s Flip Plugin Works by GreenSock ( @GreenSock) on CodePen. Sometimes you'll need to deal with state changes that you can't control, or reparenting of elements. Maybe a thumbnail image needs to transition to fill the viewport with position: fixed, or a grid of elements must get smoothly re-ordered within a flexbox container. This is where Flip Plugin shines! And now it's included in the public downloads and CDN! That's right, Flip Plugin isn't just for Club GreenSock members anymore (but seriously, if you haven't joined yet, what are you waiting for?). And for those who are members, don't worry - we've got something fun coming just for you in the future. Here's an example where a video that's in the flow of text seamlessly transitions into position: fixed in the corner when you scroll far enough: See the Pen Flip Video by GreenSock (@GreenSock) on CodePen. Even when the original position of elements could change - like in this spinning container, FLIP will handle the transition with ease. See the Pen Spinny flipz by GreenSock (@GreenSock) on CodePen. And here's a fan-favorite showing a grid of tiles you can filter by color and Flip smooths everything out: See the Pen Tiles by GreenSock (@GreenSock) on CodePen. Wanna learn about all the nitty-gritty details? Watch this video: New additions to the keyframe syntaxNew additions to the keyframe syntax Keyframes are a great way to animate a target through multiple steps while keeping your code nice and concise. You can think of them as a sub-timeline nested inside a tween Here's a reminder of the existing syntax. gsap.to(".elem", { keyframes: [ {x: 100, duration: 1}, {y: 200, duration: 1, delay: 0.5}, //create a 0.5 second gap {rotation: 360, duration: 2, delay: -0.25} //overlap by 0.25 seconds ] }); New options Percent-based keyframes This familiar syntax will make porting animations over from CSS a breeze! Instead of using delays and duration in the keyframes themselves, you specify the styles you want at certain waypoints during the animation, and just like CSS, if you omit a property from one of the keyframes the value will interpolate across that gap. gsap.to(".elem", { keyframes: { "0%": { x: 100, y: 100}, "75%": { x: 0 }, "100%": { x: 50, y: 50 } }, duration: 2, }) Array-of-values Just define an Array of values and they'll get equally distributed. So simple! And you don't need to make sure the Arrays are equal in length. Plenty of flexibility. gsap.to(".elem", { keyframes: { x: [100, 0, 50], y: [100, 0, 50] }, duration: 2 }) Demos With Object keyframes and Percentage keyframes you can drill down and add different eases into individual keyframes. See the Pen Bounce Party with GSAP keyframes, by GreenSock (@GreenSock) on CodePen. You can even combine multiple easing properties, keyframes and normal tween values. 🤯 gsap.to(".box", { keyframes: { y: [0, 80, -10, 30, 0], ease: "none", // <- ease across the entire set of keyframes (defaults to the one defined in the tween, or "none" if one isn't defined there) easeEach: "power2.inOut" // <- ease between each keyframe (defaults to "power1.inOut") }, rotate: 180, ease: "elastic", // <- the "normal" part of the tween. In this case, it affects "rotate" because it's outside the keyframes duration: 5, stagger: 0.2 }); See the Pen keyframe easing by GreenSock (@GreenSock) on CodePen. And more... GSAP 3.9 also delivers various bug fixes, so we'd highly recommend installing the latest version today. There are many ways to get GSAP - see the Installation page for all the options (download, NPM, zip, Github, etc.). Resources Full release notes on Github Full documentation Getting started with GSAP Learning resources Community forums FLIP Plugin docs More information about keyframes Happy tweening!
    8 points
  14. Looping back with a codepen. ✨ https://codepen.io/cassie-codes/pen/zYdxopE
    8 points
  15. Hi Sandy! You're animating <g> elements, so you're scaling a container. You need to get more granular and target the shapes. And I would set the transform origin ahead of time. For example, your circles could be like this. gsap.set("#circles circle", { transformOrigin: "50% 50%" }); ... .from("#circles circle",{opacity:0,scale:0,duration:2}) But it would probably better to just give your circles the same class name to make target easier. <g> <circle class="circles st6" cx="775.79" cy="197.35" r="5.81"/> <circle class="circles st6" cx="370.82" cy="55.65" r="5.81"/> <circle class="circles st7" cx="595.77" cy="70.42" r="5.81"/> </g> The zigzag could be done with the DrawSVGPlugin, or maybe by animating a clipPath. For beginners, I would recommend checking out @PointC's MotionTricks and @Carl's CreativeCodingClub.
    8 points
  16. Ooh, this was a fun experiment. I just pasted the SVG <path> data string into the CustomEase editor to convert it, then copied the results into a CustomEase that's used in an animation of the dot's "y" value to -140 because that's the tallest peak and BOOM: https://codepen.io/GreenSock/pen/abWLgwY?editors=0010 🎉 That'll be much more performant than that StackOverflow post thing that constantly loops to try to find the closest x value.
    8 points
  17. oh, ok, probably best to continue in that thread. It was very nice for @Ali Manuel to help you but we don't typically have the capacity to rebuild other people's projects on demand with new specifications. While I'm here though I believe making this full-screen will require some significant changes to the CSS and it's not really something that you would do with GSAP. If you have a question related to GreenSock animation please don't hesitate to ask.
    8 points
  18. Okay, I think I get it. I made a couple demos for you. I used a wider path just so it's easier to see what's happening. You could use gradientTransform like in your 2nd demo, but I'm not sure that gets the desired result and I have no idea about browser compatability on that one. https://codepen.io/PointC/pen/a774175618d8c17aa07fcd59e28119ed My preference would be to animate the x1/x2/y1/y2 attributes. I'd also use objectBoundingBox (default) for the gradientUnits. In this case I find it a bit easier to use values from 0 → 1 rather than keep track of absolute coordinates when using userSpaceOnUse. https://codepen.io/PointC/pen/jOBwLWw Here's a fork of your pen with option 2. https://codepen.io/PointC/pen/cae50d4609e6e0e8a1b44811aa3d278d Hopefully that helps.
    8 points
  19. I remember these two canvas based examples not GSAP specific. But each impressive none the less yielding similar result. https://codepen.io/waaark/pen/VbgwEM https://codepen.io/Zaku/pen/JNxKKY
    8 points
  20. And now I've gone even further down the 3D cube rabbit hole –made a Draggable version: https://codepen.io/creativeocean/pen/poRyMLX?editors=0010
    8 points
  21. lol. then that's probably a good place to stop. Unfortunately, the many folks like @PointC that have volunteered countless hours of their time over the years don't often have the luxury of making sure that every line of code is understandable to everyone of every skill level that passes by. The original poster was already satisfied so there's really no need for a committee to come in to do a code review. If you have an alternative, cleaner solution that would certainly be a welcome addition that would add value to the thread. If something isn't clear you can simply ask for an explanation. That's much better than calling it "over-engineered" and yet somehow at the same time criticizing it for not being forward-thinking enough to handle an ad-server injecting an ad into the middle of it 🙄 It's great that you started in this thread by trying to help. That's exactly what makes this place so great. There's loads of opportunity to help people, offer solutions, be a part of the community, make it better, and have your own voice around here. Stay positive, offer solutions, and you'll be amazed at how much more fun it is around here and how much you discover along the way!
    8 points
  22. Hey, A little experiment on how ScrollTrigger and snap could be used. Just for info. Happy tweening ... Mikel
    8 points
  23. In case it's helpful to anyone else, I put together a demo that has directional snapping, variable width sections, and nav links: https://codepen.io/GreenSock/pen/xxEQNBB?editors=0010 🎉
    8 points
  24. Hey @hastalavistababy welcome to the forum! `scale` is part of the `transform` property of CSS and it does not interact with the flow of your content, so if you do want it so that elements are pushed around when things are scaled I would use the property `fontSize` https://codepen.io/mvaneijgen/pen/ExoBoaz?editors=0110 I had to change your code a bit and had to set a fixed height on the `.logo` block, otherwise the block height would get recalculated based on the font size and you want it to stay at the bottom. Also know you can use the plugin SplitText to dynamically split text on the fly no need to manually split any text https://codepen.io/mvaneijgen/pen/XWVLVLm
    7 points
  25. Can't wait to see what you make pals!
    7 points
  26. Hi @glenhodges Welcome to the forum. Yep - just like @Cassie mentioned, morphSVG would make this pretty easy. Here's a quick version to show you the basics. https://codepen.io/PointC/pen/PoEGNjm MorphSVG is a Club GreenSock perk so you can check that out too. Happy tweening and welcome aboard.
    7 points
  27. Have you ever been in a situation with GSAP where you needed a higher level of control over conflicting tweens? If you’re just creating linear, self-playing animations like banner ads, chances are the default overwrite mode of false will work just fine for you. However, in cases where you are creating tweens dynamically based on user interaction or random events you may need finer control over how conflicts are resolved. Overwriting refers to how GSAP handles conflicts between multiple tweens on the same properties of the same targets at the same time. The video below explains GSAP’s overwrite modes and provides visual examples of how they work. Want to master GSAP? Enroll in CreativeCodingClub.com and unlock 5 premium GreenSock courses with over 90 lessons. New lessons like this one are added weekly to keep your learning fresh. GSAP’s 3 Overwrite Modes false (default): No overwriting occurs and multiple tweens can try to animate the same properties of the same target at the same time. One way to think of it is that the tweens remain "fighting each other" until one ends. true: Any existing tweens that are animating the same target (regardless of which properties are being animated) will be killed immediately. "auto": Only the conflicting parts of an existing tween will be killed. If tween1 animates the x and rotation properties of a target and then tween2 starts animating only the x property of the same targets and overwrite: "auto" is set on the second tween, then the rotation part of tween1 will remain but the x part of it will be killed. Setting Overwrite Modes // Set overwrite on a tween gsap.to(".line", { x: 200, overwrite: true }); // Set overwrite globally for all tweens gsap.defaults({ overwrite: true }); // Set overwrite for all tweens in a timeline const tl = gsap.timeline({ defaults: { overwrite: true } }); Below is the demo used in the video. Open it in a new tab to experiment with the different overwrite modes See the Pen overwrite demo by SnorklTV(@snorkltv) on CodePen. Hopefully this article helps you better understand how much control GSAP gives you. Overwrite modes are one of those features that you may not need that often, but when you do, they can save you hours of trouble writing your own solution. For more tips like this and loads of deep-dive videos designed to help you quickly master GSAP, check out CreativeCodingClub.com. You’re going to love it.
    7 points
  28. Just Added Width Expansion to my codepen above, feel free to adjust the Easing and Duration to match your Needs (Tranform X Y -50% doesn't seem to be working in this miniviewer, open codepen in another tab for correct display) https://codepen.io/blitzve0/pen/vYJGPaa
    7 points
  29. Hi @blizve0 Here's a fork of your demo with some custom hooks, which should optimize it tad bit more. Cursor Jelly Blob (codepen.io)
    7 points
  30. Hey @Syed Azam, welcome to the forum! 💚 You can do something like this: https://codepen.io/nicofonseca/pen/e81138427318c2826079e5c3f2ac4d41?editors=1010 The trick to achieve the mask effect is move the parent element to a direction and they child element to the opposite at the same time. gsap.to(parentElement, { xPercent: -100, duration:1 }); gsap.to(childElement, { xPercent: 100, duration:1, }); I hope this can help you. 🙂
    7 points
  31. Hi @Sibteali Baqar Welcome to the forum. Looks like the problem is that your orbit path (#ellipse_1) is a filled path so the circle wouldn't animate along it as you expect. I've created a little demo using your SVG. The path you were using has no fill and a red stroke. See how the circle would orbit along the outside of that path? Probably not what you want here. I added a simple ellipse and converted it to a path to show you that everything is working correctly with the MotionPathPlugin. I'd think an actual ellipse would be the easiest method here. https://codepen.io/PointC/pen/576a99f87ecf0a9aea713b8beb894f00 Hopefully that helps. If you have additional questions, you'll need to create a demo. Just strip it down to the minimum like I did above and we'll be able to provide the most accurate and helpful answers. Happy tweening and welcome aboard.
    7 points
  32. Hey DoPhuongAnh, Welcome to the GreenSock Forum. It's a lot of fun: a color 'kaleidoscope'. https://codepen.io/mikeK/pen/powWwMm Happy scrolling ... Mikel
    7 points
  33. Yep. Here's how you can leverage the MorphSVGPlugin to animate along a motion path. Animate Motion Path (codepen.io)
    7 points
  34. *** UPDATE 9/10/21 THIS PROMOTION HAS ENDED *** Hey All, I'm doing a test run of a special promotion for all Club GreenSock members (Green, Shockingly, and Business). If you've invested your money in the awesome bonus plugins and the ongoing support of the platform I'm happy to offer you 50% savings on Lifetime access to my comprehensive and extremely specialized GreenSock training available at www.CreativeCodingClub.com. For those that don't know, I've spent nearly a decade in these forums and 7 years working at GreenSock helping folks learn the ins-and-outs of the platform. The Creative Coding Club courses are in simplest terms a collection of all the tips and tricks I've learned throughout the years helping frontend developers excel at GreenSock animation and avoid common beginner pitfalls. Unlike typical "one and done" courses, the Creative Coding Club is a subscription-model that gives you access to 5 premium courses PLUS new lessons every week (over 120 now). If you've spent any time in the GreenSock docs or these forums you've probably encountered my videos and demos so I'm not going to bombard you with a hard sell... just a killer deal: 50% off a Lifetime Subscription to Creative Coding Club (exp 9/8/21) To get this deal you just have to send me a Personal Message (PM) through the GreenSock site requesting a coupon code. Once logged into the GreenSock site follow these instructions Once I receive your message I'll confirm your Club GreenSock membership status (by viewing your profile) and send you a coupon code. I'll do my best to get it to you quickly (within 2-12 hours), but understand I do sleep and work Please review the following before purchase: This promotion is being run by Creative Coding Club. GreenSock isn't involved with the selling, maintenance, or delivery of this training. I offer a 28-day 100% money back guarantee. Just send me a note requesting a refund and it's yours. This offer is only available to new Creative Coding Club students. This offer is only available to people with an active Club GreenSock membership. This offer is only available to 1 member of a Multi-Developer Club GreenSock account. Contact me for info on team plans. You must request your coupon prior to 9/8/21. Coupons must be used before 9/15/21. Let's keep this simple. If you're a Club GreenSock member and ready to commit to mastering the art of GreenSock animation through my Creative Coding Club courses and weekly lessons, send me a personal message (as outlined above) and I'll get you going. Carl *** UPDATE 9/10/21 THIS PROMOTION HAS ENDED *** Not a Club GreenSock member? Well, this is the best time to join Club GreenSock, gain access to the bonus plugins, AND grab this incredible deal on my training. Remember, to get 50% off my training you must be a Club GreenSock member prior to enrolling. If you're not a Club GreenSock member but still would like me to guide you on your training journey I have a little something for you too. Save 20% on 1 Year or Lifetime memberships to Creative Coding Club (exp 9/8/21) Visit creativeCodingClub.com Select 1 Year or Lifetime plan Use code: gsforums at checkout
    7 points
  35. 🐸 https://codepen.io/GreenSock/pen/NWgrqpG?editors=1111
    7 points
  36. It is an interesting challenge...I got sucked in and whipped together this solution: https://codepen.io/GreenSock/pen/powvxNx?editors=0010 It basically uses a "y" animation to fake the scroll on sections that are taller than the window height. Is that what you were looking for?
    7 points
  37. my advice would be to create 1 timeline that does the full circle animation. tween the progress of that timeline to any value you want below the progressTl shows the syntax for tweening the progress of the circle's timeline (tl). you can create tweens any way you want and pass them the progress from the data attributes or whatever. https://codepen.io/snorkltv/pen/mdmYVEL?editors=1010 hopefully this points you in a direction that works for you. also, if you just need to animate the stroke of a circle, it would be much easier using DrawSVG:
    7 points
  38. 🤔 Well, I'm also not sure what the desired outcome is here. But since you are moving things in a 3-dimensional space and using the PerspectiveCamera here, there is no need to 'apply' a parallax effect in any special way between different 3D elements - it is already there. If you'd want it to feel parallax(ish) in relation to the background, I guess you'd just have to make sure that your elements move faster than the background does. In the end what exactly you want to achieve comes down to camera positioning and movement of either the elements or the camera ( one might be better suited than the other, depending on what you want to do, I guess). Here is an example with ScrollTrigger's smoothScroll() helper-function included for the smooth-scrolling effect (first example pen on the .scrollerProxy() documentation page). Maybe that helps get in the right direction https://codepen.io/akapowl/pen/d48ab3a40f7f8614db9e6f460c331704
    7 points
  39. Hi @minhcd, GSAP can definitely animate canvas. And it looks like that Marx site is using GSAP is some way shape or form. Here's a super simple example on animating canvas with gsap: https://codepen.io/elegantseagulls/pen/gObyOwQ?editors=0010 If your diving into the WebGL world, the concept is basically the same: either create an object, or use known property values/variables that gsap can access. PixiJS plugin example: https://codepen.io/elegantseagulls/pen/qBEwjPV?editors=0010 Custom GSAP animated shader with ThreeJS shapes: https://codepen.io/elegantseagulls/pen/zYBeqmq?editors=0010 There's some good tutorials on how to do some of these sorts of effects (usually on images, but can easily be applied to a logo) if you do some searching. Warning though: WebGL definitely has a learning curve, so if you're new to development, it will be a very steep slope.
    7 points
  40. Hi @rcneil, You can just add another tween to take care of scaleing. Something like: gsap.to("#graphic-1", { duration:5, repeat: -1, ease: "none", scale: .2, yoyo: true, }); would do the trick. Looking at your animation, though here's a few things that could help simplify: 1: Combine the graphics into a single tween and loop/offset them with stagger 2: Comnbine motionPath and scale tweens into a single timeline Check it here: https://codepen.io/ryan_labar/pen/rNywmLX?editors=0010
    7 points
  41. Alternately - you could use masking and SVG paths for the fluid part. Here's a liquid morphing demo - (a lot of it is in the setup) @PointC has a great article here if you want to dig in. https://codepen.io/osublake/pen/BYwgBg And a much simpler liquid mask without morphing https://codepen.io/cassie-codes/pen/RwRORqB?default-tab=result&theme-id=18940
    7 points
  42. @Jim Nayzium, A tween is just that, a single tween of one or more properties on a matched element or elements. A single element https://codepen.io/sgorneau/pen/wvJKVwK Multiple matched elements https://codepen.io/sgorneau/pen/GRWpVKV A timeline contains one or more tweens that have timing controls to dictate when they begin and end on the timeline. The can begin relative to the timeline (at absolute positions .. like 0, 5, 20) , relative to each other ("+=3", "-=2",), or at named labels ("someLable"). You would use a timeline where sequencing is necessary. A simple timeline https://codepen.io/sgorneau/pen/eYvpqYG A more complex timeline https://codepen.io/sgorneau/pen/gOmaVpO?editors=0010 As far as variables go, with regard to both a tween and a timeline, a variable is used to reference that tween or timeline in the future. It's that simple. Neither require a variable, but it can make life easier to store them in variables at times, especially timelines. With the "more complex" timeline above, things are good ... until I need to dynamically add to the timeline or manipulate in some way later (pause, reverse, etc.). There is no reference to it. Once I'm stop chaining methods .. it's done. But, if I hold it in a variable to reference, I can do a lot with it. I can add tweens to it based on future logic, I can reverse it. I can jump to a specific timestamp or label. https://codepen.io/sgorneau/pen/jOBbgqB
    7 points
  43. Ah, I chased this down to a decimal precision thing. Basically, GSAP rounds to the closest 4 decimal places in order to solve various problems like: Binary math rounding. Example: 4 % 0.8 should be 0.8 but computers return 0.7999999999999998, so rounding fixes that Too many decimal places can cause the browser to introduce scientific notation and then if that gets put into a string (like for CSS when you've got units), 0.0000001 could become 1e-7 which can cause failures when the browser tries to read that value back in. Like 1e-7px - the browser is like "huh?" Memory savings for strings. For example, SVG path data strings have a lot of numbers crammed into them, so reducing the number of decimal places can save quite a bit of characters that get shoved into that string. However, when you've got a super long timeline and ScrollTrigger scrubs the progress (a value between 0 and 1), those decimal places represent more timeline real estate. In other words, going from 0.0002 to 0.0003 can feel like a bit of a jump. In the next GSAP release, I'll add two extra decimal places on generic value tweens (this doesn't affect CSS, for example). Here's a fork of your CodePen with that beta file in place: https://codepen.io/GreenSock/pen/KKWdLRE?editors=0010 (Nothing changed except the core GSAP file) Better? The reason Gannon's didn't exhibit that behavior was because it was using a totally different technique that was creating a new tween on every update, and that tween was animating the frame number which doesn't have the tiny decimals that a progress value would. It's far less efficient, but it appeared smoother due to the rounding stuff which is only apparent in long animations where those extremely small decimals represented larger chunks of time. Make sense?
    7 points
  44. My recipe a little trial & error and remove the ****. https://codepen.io/mikeK/pen/VwwwGrd Happy morphing ... Mikel
    7 points
  45. Greensock is incomparable, and I just wanted to say thank you @GreenSock and all parties involved for making this unbelievable product.
    7 points
  46. We're looking for an independent front-end developer and creative technologist who loves animation and helping people. A great fit for this role would be someone who is: Independent – This role has a lot of independence. We’re looking for someone who is comfortable with being given an idea and running with it. When they see something that needs improvement, they take initiative and either tackle it themselves or delegate it to the appropriate person. A community builder – A major part of this role is investing into the GSAP and animation community both in the GSAP forums and beyond. Responsible – With so much flexibility, this role requires someone who is reliable and able to hold themselves accountable as well as keep track of and prioritize tasks. This is not a job for someone who needs to be told each day what to work on. Entrepreneurial – GreenSock is a small company and the person in this role can help shape the direction of the company and its products. We’re looking for a sharp go-getter. Responsibilities Answer questions and facilitate these forums alongside the current moderators. Basically the "Chief Moderator" assisting the community. Generate and implement ideas to help people use GSAP more effectively. Tutorials, demos, videos, etc. Maintain the GreenSock website (content and the front-end code). Manage GreenSock's social media presence (Twitter, CodePen, Facebook). Help spread the word. Generate and implement ideas that make GreenSock more profitable and useful to the developer community. Required skills A solid understanding of the fundamentals of HTML, CSS, JavaScript, and SVG Experience with GSAP Debugging skills, especially JavaScript Some experience working with git, modules, and front-end frameworks Bonuses Expert-level experience in animating various web technologies (WebGL, SVG, Canvas, CSS, and libraries/frameworks) A good sense of visual design A good sense of motion design Experience teaching others Experience building communities Experience creating videos React experience Back-end experience, especially InVision Power Systems (IPS) experience Perks Flexible hours Work 100% remotely Interested? Email us your resume along with links to the animations you're most proud of working on. Or you can send me a direct message via the forums.
    7 points
  47. Hey @sorciereus, You could also use gsap.utils.shuffle() and stagger methods - and a motionPath and ... https://codepen.io/mikeK/pen/PobOwjN Happy landing ... Mikel
    7 points
  48. this demo should help https://codepen.io/snorkltv/pen/JjowpLO
    7 points
  49. Heya! Remember I said I was working on a Svelte project that would be needing some GSAP? Here are some of the barebones examples I made using GSAP and Svelte. onMount: https://svelte.dev/repl/94885eb0f90045da934ed5fd9f7fdb2a?version=3.29.0 Transition directive: https://svelte.dev/repl/1f70e16d637945fa8788fafafb481454?version=3.29.0 In/Out directives: https://svelte.dev/repl/000b2f192c204cd799dbb4f6d70a1c21?version=3.29.0 Action directive: https://svelte.dev/repl/eb2f99e9f3324e25af4eaada0389eed6?version=3.29.0 Animation directive: (TO-DO soon). Hope this helps.
    7 points
×