Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...

Search the Community

Showing results for tags 'gsap'.



More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Forums

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

Product Groups

  • Club GreenSock
  • TransformManager
  • Supercharge

Categories

There are no results to display.


Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


Personal Website


Twitter


CodePen


Company Website


Location


Interests

Found 607 results

  1. I want to do scroll down animation using GSAP ScrollTrigger in my Angular project like this . https://codepen.io/sanjuu01/pen/vYLmPPV?editors=1010 I tried this but this is not working. I don't know where i did a mistake. How to solve this import {Component, HostListener, OnInit } from '@angular/core'; import 'gsap'; import {TimelineMax} from 'gsap/gsap-core'; import Draggable from 'gsap/Draggable'; import ScrollTrigger from 'gsap/ScrollTrigger'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { scrollBox = new TimelineMax({paused: true, reversed: true, scrollTrigger: { trigger: '.box', pin: true, start: 'top top', end: 'bottom bottom', markers: true, toggleActions: 'play none none reverse', } }); constructor() { } ngOnInit() { this.scrollTgr(); gsap.registerPlugin(ScrollTrigger, Draggable, MotionPathPlugin); } scrollTgr() { this.scrollBox.from('.box', { y: 30, opacity: 0 }); this.scrollBox.to('.box', { y: 0, opacity: 1 }); this.scrollBox.play(); } } https://stackblitz.com/edit/angular-scroll-trigger?file=src%2Fapp%2Fapp.component.ts
  2. Hi, I'm trying to get an effect of a collection of shapes to come together and fit together (though some of the paths need a clean up 😅) I have made a few simple ScrollTrigger animations and can arrange the shapes into where they should be / the general animation however.... I'm really stuck on how to get the shapes on the bottom on the vector to act as a mask for the background image the animation is placed upon. I'm able to make a compound path a set the mask but wondered if anyone had any ideas around how I would be able to mask as well as animate the shapes independently (as they are moving on the y-axis at different heights). Any help would be appreciated!
  3. Learn to control your animations on scroll with GreenSock's powerful ScrollTrigger in this mini-course by SnorklTV.
  4. POST RESOLUTION EDIT: See Zach's comment below for a more modern approach to this problem. ---- Hi there. I have a responsive site where I want the content to stagger reveal as the user scrolls. The issue I'm having is that on load, the first few items (depending on screen height) are above the trigger and therefore just animate in together as opposed to staggered. Is there a way to have it so that the content that loads immediately staggers, and then the remaining elements animate like normal on scroll via ScrollMagic? ScrollReveal has a pretty good example of what I'm going for, with content staggering in on load, followed by then animating the lower elements in on scroll. Thanks!
  5. Hi! I'm trying to achive the effect that on scroll down/up GSAP animation will play and change the section content and after it reaches the last section it will display first section content and so on if scroll up on first content it display last content, but the eventListener is added on wheel, because I want to prevent page scroll, and here is the problem. If you scroll while the animation is playing it will display wrong content and if you scroll too many times the incrementation / decrementation will brake the code, so my question is: can I disable mouse wheel on a time when the animation is playing? Tried to use preventDefault() on event, but it didn't work at all. It's this codepen: Codepen Also I'm sorry if the solution is kinda messed up, but this was the only thing that came to my mind. Then after I asked this question on StackOverflow I recived the information that I can use .then(), but the problem is that when i change everything up then there is still a small problem, that if i scroll even few times while the animation is playing, then the animation is played again this many time it detects mouse wheel. Codepen 2. So here is my question. Can i somehow change it up, so it will not animate multiple times and will not break whole code? Sorry for not putting code here, but it is a lot of it. Also I know it's not really a GSAP problem but I think I would recive better solution here. Cheers!
  6. //This is a onclick function which gets triggered on a button click which is responsible to animated each node to some coordinates defined startAnimation: function(){ // condider findThechildrens function pushes 21 childrens in the global array (function defined below) //please if anyone has any idea to make this code modular and not repetative please help findTheChildrens(); var tween1 = new gsap.timeline(); var tween2 = new gsap.timeline(); var tween3 = new gsap.timeline(); var tween4 = new gsap.timeline(); var tween2 = new gsap.timeline(); var tween3 = new gsap.timeline(); var tween4 = new gsap.timeline(); var tween5 = new gsap.timeline(); var tween6 = new gsap.timeline(); var tween7 = new gsap.timeline(); var tween8 = new gsap.timeline(); var tween9 = new gsap.timeline(); var tween10 = new gsap.timeline(); var tween11 = new gsap.timeline(); var tween12 = new gsap.timeline(); var tween13 = new gsap.timeline(); var tween14 = new gsap.timeline(); var tween15 = new gsap.timeline(); var tween16 = new gsap.timeline(); var tween17 = new gsap.timeline(); var tween18 = new gsap.timeline(); var tween19 = new gsap.timeline(); tween17.to(this.tweenArr[1].position, { duration: 10, x: 10, ease:Linear.None }); tween18.to(this.tweenArr[2].position, { duration: 10, x: -10, ease:Linear.None }); tween14.to(this.tweenArr[3].position, { duration: 10, x: 20, ease:Linear.None }); tween5.to(this.tweenArr[4].position, { duration: 10, z: 15, ease:Linear.None }); tween6.to(this.tweenArr[5].position, { duration: 10, z: 15, ease:Linear.None}); tween7.to(this.tweenArr[6].position, { duration: 10, z: 15, ease:Linear.None}); tween8.to(this.tweenArr[7].position, { duration: 10, z: 15, ease:Linear.None }); tween9.to(this.tweenArr[8].position, { duration: 10, x: 25, ease:Linear.None}); tween10.to(this.tweenArr[9].position, { duration: 10, x: 25, ease:Linear.None }); tween1.to(this.tweenArr[10].position, { duration: 10, x: -20, ease:Linear.None }); tween2.to(this.tweenArr[11].position, { duration: 10, x: -20, ease:Linear.None}); tween3.to(this.tweenArr[12].position, { duration: 10, x: -20, ease:Linear.None}); tween4.to(this.tweenArr[13].position, { duration: 10, x: -20, ease:Linear.None }); tween11.to(this.tweenArr[14].position,{ duration: 10, y: -20, ease:Linear.None}); tween12.to(this.tweenArr[15].position,{ duration: 10, y: -20, ease:Linear.None }); tween19.to(this.tweenArr[16].position,{ duration: 10, x: 15, ease:Linear.None }); tween13.to(this.tweenArr[17].position,{ duration: 10, x: -15, ease:Linear.None }); tween16.to(this.tweenArr[19].position,{ duration: 10, z: 5, ease:Linear.None }); tween15.to(this.tweenArr[20].position,{ duration: 10, z: 10, ease:Linear.None }); }, //This functions gets called only one time which is responsible to tranverse the assembly and keep all found childrens into a global array (tweenArr) findTheChildrens : function(){ this.findTheChildrens = function(){}; var node = scene.children[2].children[0]; for (var i = 0; i < node.children.length; i++) { var childNode = node.children[i]; if (childNode.children.length > 0) { if (childNode.children[0].type == "Group" || childNode.children[0].type == "Mesh") { this.tweenArr.push(childNode); } } } },
  7. Hi guys! This is my first post ever, I'm new to GSAP and I'm soooooooooo stuck, I need your help I'm creating a series of cards (length varies) that scroll vertically and infinitely, I've been able to achieve that, however, at every point, there should be an active card that appears expanded than the rest and that card is usually the one that's positioned at the middle of the view port... That is, as the cards scroll up vertically, whichever card is at the vertical middle should expand and once it's gone above the middle section of the viewport, the card below it should now become expanded, and so on... so, at any given time, a card should be in focus... I'm VERY new to GSAP and this has kicked my ass for about a month, Please I'd appreciate some help here, Thanks Also, please let me know if my code can be improved... BTW, this is how the expanded card looks in motion: Note: I must also mention that, the way I have this implemented in my actual code (Gatsby application), each card gets a prop - active - and whenever active is set to true, the classes that cause the expansion are applied... So, a solution that would work out of the box for me is one that updates the state of a particular card whenever it's in the viewport... so, something that checks and updates the prop of the card... if this isn't good for performance I'm ready to stick with whatever works... Thanks so much:
  8. Hi! How can i animate text from last character to first? I can't find any demo about it. Thank you!
  9. Hi everone, I am new to Greensock and playing around with the recipies I have found in tutorials. I tried adding layered pinning from this example into React app. Pinning does work, but I have an issue with snapping. I am importing gsap and ScrollTrigger as module. Below is a simplified (no css classes) code // src/index.js import React from 'react' import { render } from 'react-dom' import { App } from './components/app' import { gsap, ScrollTrigger } from 'gsap/all' gsap.registerPlugin(ScrollTrigger) render( <App />, document.getElementById('root') ) // src/components/app/index.js import React, { useEffect, useRef } from 'react' import { ScrollTrigger } from 'gsap/all' export const App = () => { const refSlide1 = useRef(null) const refSlide2 = useRef(null) const refSlide3 = useRef(null) const refSlide4 = useRef(null) const refSlide5 = useRef(null) useEffect(() => { const sections = [refSlide1, refSlide2, refSlide3, refSlide4, refSlide5].map(ref => ref.current); sections.forEach((panel, i) => { ScrollTrigger.create({ trigger: panel, start: "top top", pin: true, pinSpacing: false }); }); ScrollTrigger.create({ snap: 1 / (sections.length - 1) }); }, [refSlide1, refSlide2, refSlide3, refSlide4, refSlide5]) return ( <div className={style.app}> <section ref={refSlide1} /> <section ref={refSlide2} /> <section ref={refSlide3} /> <section ref={refSlide4} /> <section ref={refSlide5} /> </div> ) } Full code can be found in the repo. npm install && npm run start would run it on localhost:3000. I am working it around by installing GSAP and ScrollTrigger via script tag (see master and diff), and then it works. But I'd like to eventually figure out how to make it work with imports. Any tips on how what to look at? Thanks, Sasha
  10. Hi guys, a bit new to this gsap thing. I saw a few threads around here talking about how to use gsap for landing animations that also utilise localstorage. I have some code at the moment for this, but it seems as if gsap is breaking on the initial load, cancelling the animation entirely import React, {useRef, useEffect} from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import Nav from './nav' import {TweenMax} from 'gsap' ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root'); ); export default function App() { let app = useRef(null); let loader = useRef(null); var animPlayed = localStorage.getItem("loadingAnimPlayed"); console.log(animPlayed); if (!animPlayed) { // This is the localstorage animation to be run. console.log("Loader run"); TweenMax.to(loader, 1, { opacity: 1, onComplete: function() { localStorage.setItem("loadingAnimPlayed", true) } }) } useEffect(() => { TweenMax.to(app, 0, {css: {visibility: "visible"}}) }, []) return ( <> <div className="loader" ref={el => {loader = el}}></div> <div className="page" ref={el => {app = el}}> <div className="header"> <Nav /> </div> </div> </> ) } I get a series of errors on the first load, when the condition of the animation are met, the main one being: "TypeError: Cannot add property _gsap, object is not extensible" I'm not sure how to fix my code in order to get the animation to run. Any ideas?
  11. Hi! I have a problem using draggable plugin with DrawSVG plugin. I have a clock which I can drag to move hands. When I release (dragend), a timer is starting. But if I want to update timer when timer is in progress, I can't reset svg. So more I update, more the svg decreases quicky. Do you have any idea? Thx a lot I'm sorry i don't know how to import libs on codepen... :/
  12. With over 100,000 posts in the popular GreenSock forums, we've noticed some common mistakes that you'd be wise to avoid. We threw in a few tips as well. Here is a summary of the mistakes: Creating from() logic issues Not setting ALL transforms with GSAP Not using xPercent and yPercent Recreating animations over and over Adding tweens to completed timelines Not using loops Using the old/verbose syntax Creating from() logic issues It's usually smart to use .to() and .from() tweens instead of .fromTo() because they're more dynamic - they pull either the starting or ending values from whatever they happen to CURRENTLY be at the time that tween renders for the first time. It’s one of the tips in the article on animating efficiently. But be careful because that dynamic nature can bite you in a few scenarios. First, keep in mind that .from() tweens go from the provided value to the current value. Take a look at this example: See the Pen Illustrating .from() effects - Part 1 by GreenSock (@GreenSock) on CodePen. Try clicking it one time and letting it play. It works, fading in the element. Now try clicking it multiple times right after each other. The box stops showing up because it uses the current opacity as the end point which, if the animation has not completed, is some value less than 1. The fix for this is simple: use a .fromTo(). Alternatively you could create the animation beforehand and use a control method (we'll talk more about this approach later in this article). See the Pen Illustrating .from() effects - Part 1 by GreenSock (@GreenSock) on CodePen. Second, keep in mind that by default immediateRender is true by default for .from() and .fromTo() tweens because that's typically the most intuitive behavior (if you're animating from a certain value, it should start there right away). But if you create a .from() tween after a .to() tween affecting the same properties of the same object, try to figure out what will happen: const tl = gsap.timeline() tl.to(".box", {x: 100}); tl.from(".box", {x: 100}); You might expect the box to animate x from 0 to 100 and then back to 0. Or maybe you'd expect it to animate from 0 to 100 and then stay at 100. Let’s see what happens: See the Pen Illustrating .from() effects - Part 1 by GreenSock (@GreenSock) on CodePen. The box animates x from 100 to 100 and then back to 0. Why is that? By default .to() tweens wait to render until their playhead actually moves (it's a waste of CPU cycles to render at a time of 0 because nothing will have changed). But since from() has immediateRender: true, x jumps to 100 immediately on the current tick! Then it runs the .to() tween on the next tick (since it’s first in the timeline) and records the current starting value which is 100! So it animates 100 to 100 over 0.5 seconds. Then it runs the .from() tween which has the cached value of 0 as the end value. If you have several timelines affecting the same element, situations like this can be a little tricky to catch. So just be mindful of how things work when using .to() and .from() tweens. They’re very powerful but with power comes responsibility. A simple solution here is to set immediateRender: true on the .to() tween, or immediateRender: false on the .from() tween. The third situation is similar but involves repeatRefresh and repeats. Let’s say you have a situation where you want a looped animation that fades in some text and fades it out. You could create a timeline, use a .from() to fade in the text, then use a .to() to fade it out: const tl = gsap.timeline({repeat:-1}); tl.set(".text", { color: "random([green, gray, orange, pink])" }, 2); tl.from(chars, { opacity: 0 }); tl.to(chars, { opacity: 0 }); This will work just fine! Here’s the same thing but staggered using SplitText to make it look a little nicer: See the Pen Fade in and out text by GreenSock (@GreenSock) on CodePen. But this only randomizes the colors at the start. What if we want new random values each repeat? That’s where repeatRefresh comes in. Let’s add repeatRefresh: true to see what happens: See the Pen Random on Reset (wrong way) by GreenSock (@GreenSock) on CodePen. The animation plays correctly the first time but after that the elements don’t fade in a second time! Why is that? repeatRefresh uses the end values of the animation as the starting values of the next iteration. In this case, the opacity of our text elements are all 0 at the end. So when the animation gets to the .from() the second time around, the opacity animates from a value of 0 to a value of 0 since the tween is relative. What we want to do instead is always animate from a value of 0 to a value of 1 so here the easiest fix is to use a .fromTo(): See the Pen Random on Reset by GreenSock (@GreenSock) on CodePen. Now it does what we want. There are other solutions like using a .set() before the .from() but most often it’s easiest to just use a .fromTo() in cases like this. Not setting ALL transforms with GSAP If you are going to animate an element with GSAP, even the initial transform values should be set with GSAP because it delivers better: Accuracy - The browser always reports computed values in pixels, thus it's impossible for GSAP to discern when you use another unit like % or vw in your CSS rule. Also, computed values are in matrix() or matrix3d() which are inherently ambiguous when it comes to rotation and scale. The matrix for 0, 360, and 720 degrees are identical. A scaleX of -1 results in the same matrix as something with rotation of 180 degrees and scaleY of -1. There are infinite combinations that are identical, but when you set transform-related values with GSAP, everything is saved in a perfectly accurate way. Performance - GSAP caches transform-related values to make things super fast. Parsing all of the components from a computed value is more expensive. If you are worried about a flash of unstyled content, you can handle that by using a technique that hides the element initially and then shows it via JavaScript as this post covers. Or you can set the initial styles with CSS rules and ALSO set them in GSAP. Not using xPercent and yPercent Did you know that you can combine percentage-based translation and other units? This is super useful if, for example, you'd like to align the center of an element with a particular offset, like {xPercent: -50, yPercent: -50, x: 100, y: 300}. We often see people use percent values in the x and y properties which is technically possible but can cause confusion at times. For example, if you set x and y to "-50%" and then later you set xPercent: -50, you'd see it move as if it's at xPercent: -100 because the x and xPercent both have -50%. Whenever you're setting a percentage-based translation, it's typically best to use the xPercent and yPercent properties. // Not recommended x: "50%", y: "50%", // Recommended xPercent: 50, yPercent: 50 Recreating animations over and over Creating your tweens and timelines beforehand has several advantages: Performance - Instead of having to create them right as they’re needed, you can do it ahead of time. Additionally, you need fewer instances of animations. Most of the time you’d never notice, but it’s good practice. Simplified logic - This is especially true when related to user interaction events. Freedom - Want to pause an animation when an event happens? Do it. Want to reverse an animation when the user does something? No problem. This sort of thing is much more difficult to handle when you create animations inside of event callbacks. Most of the time when you create animations beforehand, you will want to keep them paused until they’re needed. Then you can use control methods like .play(), .pause(), .reverse(), .progress(), .seek(), .restart(), and .timeScale() to affect their play state. Here’s a simple example: See the Pen Playing and reversing an animation on hover by GreenSock (@GreenSock) on CodePen. For more information related to creating animations beforehand, you can see the animating efficiently article. One exception to this rule is when you need things to be dynamic, like if the initial values may vary. For example, if you’re animating the height of the bars in a chart between various states and the user may click different buttons quickly, it’d make sense to create the animation each time to ensure they flow from whatever the current state is (even if it's mid-tween) like the demo below. See the Pen Playing and reversing an animation on hover by GreenSock (@GreenSock) on CodePen. Adding tweens to completed timelines A common pattern of mistakes that I’ve seen goes like this: const tl = gsap.timeline() tl.to(myElem, { x: 100 }); myElem.addEventListener("click", () => tl.to(myElem, { x: 300 }) ); Did you catch the mistake? If you add new tweens to a timeline that is already completed, they won’t be called unless you re-run the timeline. Almost always in these situations you should just use control methods for a previously created animation or create a new animation instead (not using an existing timeline) following the guidelines that we covered in the previous section. Not using loops If you want to apply the same effect to multiple elements (sections, cards, buttons, etc.) when a certain event happens to each one, you should almost always use a loop. For example, don’t use a selector like "button" when you want it to affect just one button. For example, if you wanted to fire an effect when each button is clicked: // BAD: immediately animates ALL buttons at once! gsap.effects.explode("button", { direction: "up", duration: 3 }); // GOOD: animation is specific to each button, and only when clicked gsap.utils.toArray("button").forEach(btn => btn.addEventListener("click", () => gsap.effects.explode(btn, { direction: "up", duration: 3 })) }); Inside of this loop, you can use a selector that is scoped to the given element so that you're only getting things INSIDE that element. For example: gsap.utils.toArray(".container").forEach(container => { let info = container.querySelector(".information"), silhouette = container.querySelector(".silhouette .cover"), tl = gsap.timeline({ paused: true }); tl.to(info, { yPercent: 0 }) .to(silhouette, { opacity: 0 }, 0); container.addEventListener("mouseenter", () => tl.play() ); container.addEventListener("mouseleave", () => tl.reverse() ); }); See the Pen Who&#39;s That Pok&eacute;mon? - forEach example demo by GreenSock (@GreenSock) on CodePen. Using the old/verbose syntax Drop the Lite/Max I regularly see people using the old syntax even though they are loading GSAP 3. Old habits die hard. Even though the old syntax still technically works, the new modern GSAP 3 syntax is sleeker and simpler. Plus the old syntax won't be supported in GSAP 4 (which is far off in the future, but it's still a good idea to write future-friendly code). For example instead of using something that has Lite/Max in it, just use gsap: // old TweenLite.to() TweenMax.from() new TimelineMax() // new gsap.to() gsap.from() gsap.timeline() Use the string form for eases The shorter string form of eases requires less typing and lets you avoid extra import statements in module environments. // old Power2.easeOut Sine.easeInOut // new "power2" // The default is .out "sine.inOut" Duration belongs in the vars parameter Putting the duration inside of the vars parameter does require a bit more typing, but it makes things more readable and intuitive. GSAP’s defaults and effects are very helpful but you can’t make use of them if you’re putting the duration as the second parameter. // old gsap.to(elem, 1, { x: 100 }); // new gsap.to(elem, { duration: 1, x: 100}); // using GSAP’s defaults: const tl = gsap.timeline({ defaults: { duration: 1 } }); tl.to(elem, { x: 100 }); // no duration necessary! tl.to(elem, { y: 100, duration: 3 }); // easily overwrite the default value For a more full listing of changes in GSAP 3, check out the GSAP 3 Migration Guide. Numerical values don’t usually need to be strings For example if you want to set the x transform to 100 pixels, you don’t need to say x: "100px", you can just say x: 100. Simple! The only time when you need to pass numerical values as strings are if you need to change the unit (like x: "10vw") or pass in a complex value (like transformOrigin: "0px 50px"). The target of a tween can be a selector string I often see people do something like this: gsap.to(document.querySelectorAll(".box"), { x: 100 }); Or even with jQuery: gsap.to($(".box"), { x: 100 }); Both of the above will work but could be simplified by passing a selector string in as the target; GSAP will automatically use .querySelectorAll() to get a list of all of the elements that match. So the above can be written simple as gsap.to(".box", { x: 100 }); You could also pass in a complex selector string like ".box, .card" and it will select all boxes and cards. Or use an Array of elements so long as they are of the same type (selector string, variable reference, generic object, etc.). Conclusion So how'd you do? Is your GSAP code clear of these common mistakes? Hopefully you learned a few things. As always, if you need any help, the GreenSock forums are a fantastic resource. We love to help people develop their animation superpowers. If you're looking for another great learning resource, read how to animate efficiently! Now go forth and tween responsibly!
  13. Hi guys, I built a page with multiple animations using GSAP and ScrollTrigger, this is the page Open Screenplay. The animations are very good but I need to add transitions between the sections but I don't how I can do it. The transitions that I need to apply are bounce transition like this https://connect-homes.com/process and overlap transition like this http://www.espn.com/espn/eticket/story?page=Dock-Ellis. Thanks in advance.
  14. Hi, I am working on a project using the DrawSVGPlugin, and using native JS that's compiled with gulp and webpack. I'm importing gsap and the plugin as such : import gsap, { TimelineLite} from 'gsap'; import * as drawSVG from '../gsap-extras/DrawSVGPlugin.js'; and the registering the plugin in the constructor of my component's class using : gsap.registerPlugin(drawSVG); Then, I simply want to test the plugin doing something like : new TimelineLite().set([this.anchorCircles, this.anchorFillCircles], { drawSVG: 0 }); This is actually working as long my gulp server is watching the changes and displaying the development JS, but after running a build, I'm able to log the drawSVG imported, but the TimeLine().set wont have any effect on my elements. I can't provide my gulp config if this is needed, but may be there's something simpler that I am missing here.. Thank you EDIT: // Finally found that the way the webpack was configured prevented the minified plugin to work. I had to change the webpack babili plugin to webpack minify plugin !
  15. Hey guys. First post here. I'm a graphic design and front-end student out of Zealand, Denmark. We are only learning JQuery at my school, but I am a hard learner, so I am looking for other options. I am currently learning vanilla JS, and randomly found this amazing library. So far everything has been super awesome. I'm facing one issue though. I am animating the height of an image. I added an AddEventListener, as I want the animation to start at a specific point on my site. Basically what I want to do is to animate the photo when it reaches the destination of the position. I have other things attached to the Eventlistener which works as it should. But my image keeps restarting when I scroll. Is there anything I can do to have it animate the height and then stick to that height even when I scroll. I tried adding repeat: 0, and I tried to add an onComplete. I have lots of code that works as it should. So I'll just paste the code I have issues with: function scrollAppear(){ const macbook = document.querySelector("#macbookLight"); const mbPos = macbook.getBoundingClientRect().top; const imagePos = window.innerHeight /1.5; if(mbPos < imagePos){ const tl = gsap.timeline(); tl.fromTo(macbook, 2, {height: 0}, {height: 500}); } } window.addEventListener("scroll",scrollAppear); I'd appreciate any help I can get, I have been searching Google without any luck. Thanks!
  16. I'm attempting to add GSAP to Adobe Animate, but the Actions panel is not showing Global. How do I turn that on?
  17. Thank you for creating such an amazing tool for animation and supporting community. I have a question about way how Gsap is creating an order of properties for transform while tween/set. As i understand based on documentation, skew properties come after scale properties (this is exactly what i need), but when im trying on a practice i see the opposite result where skew is coming before scale properties. Can you please help me to understand why this happen and how can i change this? I have attached codepen comparing two results: first one i've set up using css and pick the order by myself, second order was created using gsap set. Im working on complex animation, part of this animation using scale and skew properties, but im getting wrong result when skew coming before scale. Thank you so much.
  18. mush

    Nextjs and gsap

    Hi all, I did some animations with gsap and scrollscene and it working fine when I run the development environment but when I build the project and visit the page I get errors in the console. Uncaught TypeError: Cannot assign to read only property 'x' of object '#<HTMLImageElement>' I tried to add a polyfill like the scollscene docs say and I used next-transpile-modules and transpiled gsap like this but it didn't work. const withTM = require('next-transpile-modules')(['gsap']); Any suggestions?
  19. Hi, I'm new here & need some help. I have attached my Codepen here. It's the Part of a bigger Menu. My Text is coming from Left to the Right, So is the is the all of effects & animations. Is there a way to Start the Opacity/Letter-spacing from Right (end of the sentence) to the Left side? So only Text will be Ease-in from Left to Right but all of the animation (Opacity/Letter-spacing) will go from Right to Left ? Sorry, if my question is confusing. Thanks.
  20. https://codesandbox.io/s/little-pond-kfvfq I have used scroller property and markers don't move If you want to see what I want to accomplish here Delete Position: fixed in content-scroll and remove scroller property
  21. Ahmed Elabbasy

    tilt effect

    How can I change the transform to matrix I find it difficult to drag in the slider when creating the tilt effect as well as some delay in changing the slide and I think this will fix it just a belief I use gsap.to https://codesandbox.io/s/broken-currying-05h9k
  22. Hello everyone, First time using this, so please excuse my terminology. I'm doing a THREE.js animation loop, where a bunch of textGeometries animate forming a box, sphere and cone. I'm using two timelines since I don't want the first transition(from initial state to forming a box) to repeat. So when restarting the second timeline on `onComplete`, it isn't doing a smooth transition. I'm unable to track down what's causing this, could anybody please help me figure out why the restart isn't smooth? Below is the logic, followed by a codepen demo: for (i = 0; i < MAX_PARTICLES; i++) { var initialMorphTL = new TimelineLite(); var morphTL = new TimelineLite({onComplete:function(){this.restart()}}); const child = children[i]; initialMorphTL.to(child.position, 1, { ease: Elastic.easeOut.config( 0.1, .3), x: pointsInsideBox[ index ++ ], y: pointsInsideBox[ index ++ ], z: pointsInsideBox[ index ++ ], delay: .1 }).to(child.material.color, 1, { ease: Linear.easeNone, r: boxColor.r, g: boxColor.g, b: boxColor.b, }, "-=1"); morphTL.to(child.position, 1, { ease: Elastic.easeOut.config( 0.1, .3), x: pointsInsideSphere[ index ++ ], y: pointsInsideSphere[ index ++ ], z: pointsInsideSphere[ index ++ ], delay: 5 }).to(child.material.color, 1, { ease: Linear.easeNone, r: sphereColor.r, g: sphereColor.g, b: sphereColor.b, }, "-=1").to(child.position, 1, { ease: Elastic.easeOut.config( 0.1, .3), x: pointsInsideCone[ index ++ ], y: pointsInsideCone[ index ++ ], z: pointsInsideCone[ index ++ ], delay: 5 }).to(child.material.color, 1, { ease: Linear.easeNone, r: coneColor.r, g: coneColor.g, b: coneColor.b, }, "-=1").to(child.position, 1, { ease: Elastic.easeOut.config( 0.1, .3), x: pointsInsideBox[ index ++ ], y: pointsInsideBox[ index ++ ], z: pointsInsideBox[ index ++ ], delay: 5 }).to(child.material.color, 1, { ease: Linear.easeNone, r: boxColor.r, g: boxColor.g, b: boxColor.b, }, "-=1"); }
  23. The secret to building gorgeous sequences with precise timing is understanding the position parameter which is used in many methods throughout GSAP. This one super-flexible parameter controls the placement of your tweens, labels, callbacks, pauses, and even nested timelines, so you'll be able to literally place anything anywhere in any sequence. Watch the video For a quick overview of the position parameter, check out this video from the "GSAP 3 Express" course by Snorkl.tv - one of the best ways to learn the basics of GSAP 3. Using position with gsap.to() This article will focus on the gsap.to() method for adding tweens to a Tween, but it works the same in other methods like from(), fromTo(), add(), etc. Notice that the position parameter comes after the vars parameter: .to( target, vars, position ) Since it's so common to chain animations one-after-the-other, the default position is "+=0" which just means "at the end", so timeline.to(...).to(...) chains those animations back-to-back. It's fine to omit the position parameter in this case. But what if you want them to overlap, or start at the same time, or have a gap between them? No problem. Multiple behaviors You can define the position in any of the following ways At an absolute time (1) Relative to the end of a timeline allowing for gaps ("+=1") or overlaps ("-=1") At a label ("someLabel") Relative to a label ("someLabel+=1") Relative to the previously added tween ("<" references the most recently-added animation's START time while ">" references the most recently-added animation's END time) Basic code usage tl.to(element, 1, {x: 200}) //1 second after end of timeline (gap) .to(element, {duration: 1, y: 200}, "+=1") //0.5 seconds before end of timeline (overlap) .to(element, {duration: 1, rotation: 360}, "-=0.5") //at exactly 6 seconds from the beginning of the timeline .to(element, {duration: 1, scale: 4}, 6); It can also be used to add tweens at labels or relative to labels //add a label named scene1 at an exact time of 2-seconds into the timeline tl.add("scene1", 2) //add tween at scene1 label .to(element, {duration: 4, x: 200}, "scene1") //add tween 3 seconds after scene1 label .to(element, {duration: 1, opacity: 0}, "scene1+=3"); Sometimes technical explanations and code snippets don't do these things justice. Take a look at the interactive examples below. No position: Direct Sequence If no position parameter is provided, all tweens will run in direct succession. .content .demoBody code.prettyprint, .content .demoBody pre.prettyprint { margin:0; } .content .demoBody pre.prettyprint { width:8380px; } .content .demoBody code, .main-content .demoBody code { background-color:transparent; font-size:18px; line-height:22px; } .demoBody { background-color:#1d1d1d; font-family: 'Signika Negative', sans-serif; color:#989898; font-size:16px; width:838px; margin:auto; } .timelineDemo { margin:auto; background-color:#1d1d1d; width:800px; padding:20px 0; } .demoBody h1, .demoBody h2, .demoBody h3 { margin: 10px 0 10px 0; color:#f3f2ef; } .demoBody h1 { font-size:36px; } .demoBody h2 { font-size:18px; font-weight:300; } .demoBody h3 { font-size:24px; } .demoBody p{ line-height:22px; margin-bottom:16px; width:650px; } .timelineDemo .box { width:50px; height:50px; position:relative; border-radius:6px; margin-bottom:4px; } .timelineDemo .green{ background-color:#6fb936; } .timelineDemo .orange { background-color:#f38630; } .timelineDemo .blue { background-color:#338; } .timleineUI-row{ background-color:#2f2f2f; margin:2px 0; padding:4px 0; } .secondMarker { width:155px; border-left: solid 1px #aaa; display:inline-block; position:relative; line-height:16px; font-size:16px; padding-left:4px; color:#777; } .timelineUI-tween{ position:relative; width:160px; height:16px; border-radius:8px; background: #a0bc58; /* Old browsers */ background: -moz-linear-gradient(top, #a0bc58 0%, #66832f 100%); /* FF3.6+ */ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#a0bc58), color-stop(100%,#66832f)); /* Chrome,Safari4+ */ background: -webkit-linear-gradient(top, #a0bc58 0%,#66832f 100%); /* Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, #a0bc58 0%,#66832f 100%); /* Opera 11.10+ */ background: -ms-linear-gradient(top, #a0bc58 0%,#66832f 100%); /* IE10+ */ background: linear-gradient(to bottom, #a0bc58 0%,#66832f 100%); /* W3C */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#a0bc58', endColorstr='#66832f',GradientType=0 ); /* IE6-9 */ } .timelineUI-dragger-track{ position:relative; width:810px; margin-top:20px; } .timelineUI-dragger{ position:absolute; width:10px; height:100px; top:-20px; } .timelineUI-dragger div{ position:relative; width: 0px; height: 0; border-style: solid; border-width: 20px 10px 0 10px; border-color: rgba(255, 0, 0, 0.4) transparent transparent transparent; left:-10px; } .timelineUI-dragger div::after { content:" "; position:absolute; width:1px; height:95px; top:-1px; left:-1px; border-left: solid 2px rgba(255, 0, 0, 0.4); } .timelineUI-dragger div::before { content:" "; position:absolute; width:20px; height:114px; top:-20px; left:-10px; } .timelineUI-time{ position:relative; font-size:30px; text-align:center; } .controls { margin:10px 2px; } .prettyprint { font-size:20px; line-height:24px; } .timelineUI-button { background: #414141; background-image: -webkit-linear-gradient(top, #575757, #414141); background-image: -moz-linear-gradient(top, #575757, #414141); background-image: -ms-linear-gradient(top, #575757, #414141); background-image: -o-linear-gradient(top, #575757, #414141); background-image: linear-gradient(to bottom, #575757, #414141); text-shadow: 0px 1px 0px #414141; -webkit-box-shadow: 0px 1px 0px 414141; -moz-box-shadow: 0px 1px 0px 414141; box-shadow: 0px 1px 0px 414141; color: #ffffff; text-decoration: none; margin: 0 auto; -webkit-border-radius: 4; -moz-border-radius: 4; border-radius: 4px; font-family: "Signika Negative", sans-serif; text-transform: uppercase; font-weight: 600; display: table; cursor: pointer; font-size: 13px; line-height: 18px; outline:none; border:none; display:inline-block; padding: 8px 14px;} .timelineUI-button:hover { background: #57a818; background-image: -webkit-linear-gradient(top, #57a818, #4d9916); background-image: -moz-linear-gradient(top, #57a818, #4d9916); background-image: -ms-linear-gradient(top, #57a818, #4d9916); background-image: -o-linear-gradient(top, #57a818, #4d9916); background-image: linear-gradient(to bottom, #57a818, #4d9916); text-shadow: 0px 1px 0px #32610e; -webkit-box-shadow: 0px 1px 0px fefefe; -moz-box-shadow: 0px 1px 0px fefefe; box-shadow: 0px 1px 0px fefefe; color: #ffffff; text-decoration: none; } .element-box { background: #ffffff; border-radius: 6px; border: 1px solid #cccccc; padding: 17px 26px 17px 26px; font-weight: 400; font-size: 18px; color: #555555; margin-bottom:20px; } .demoBody .prettyprint { min-width:300px; } His animation is a bit out of whack and the client has the following demands for you: Man should start animating 1 second before car animation ends. One second after man animation ends both car and lift should go up simultaneously. For a visual representation of what the finished product should like, here is a .mov and .gif. Alright it's time to put your animation chops to the test. Challenge instructions Visit the editable version of the animation starter file on CodePen. Click the "fork" button to make your own copy. When you're done, tweet the CodePen link to @greensock. We'll make you feel extra special. There are multiple solutions that require only adding the proper position parameters. Some are more flexible than others, but the important part right now is that the end result meets the clients demands. .demoBody { max-width: 94vw; width: 100%; height: auto; overflow: auto; }
  24. This is a guest post from one of the best teachers of GSAP, Carl Schooff, also known as SnorklTV. If you're new to GSAP or just looking to learn about the GSAP 3 syntax, his video courses are second to none! I can't tell you how many hundred's of questions I've seen in the GreenSock forums about controlling GSAP animations on scroll. I'm so happy there is finally a genuine GreenSock tool to power the future of scroll-driven animations. Before I get into the specifics, it's worth a moment of time to honor those that got us here. A short history of Scroll-driven Animations John Polacek paved the way in 2013 with Superscrollorama, a jQuery plugin that used GSAP under the hood. Many amazing sites were created with this highly-acclaimed, ground-breaking, and trend-setting tool. In 2014 Jan Paepke took the reins and did a complete re-write and SuperScrollarama became ScrollMagic. ScrollMagic was hugely successful as it offered a slew of new features. Excellent demo files made the tool easy for beginners to understand. Awards sites exploded with many clever effects made with the ScrollMagic and GSAP combo. However, as with many solo-led open source projects, it's popularity created a hefty support burden that couldn't be managed. As issues went unanswered in the ScrollMagic repo, more users found their way to the GreenSock forums asking for support on a product GreenSock didn't create or have any way of fixing. ScrollTrigger is born On June 1st, 2020, GreenSock released ScrollTrigger to a sold out audience via a historic YouTube Premiere. ScrollTrigger was built with a totally fresh perspective on how GreenSock animations should be controlled via scroll. Not only does the API offer more features than it's predecessors, but it has a strong focus on performance which really shines in this "mobile-first" world. And as you can expect with any GreenSock product support is phenomenal. For a full list of features, you'll need to check out GreenSock's ScrollTrigger API Docs, but my job here is to get you up and running quickly... so let's go! Watch the Video This video is from my course GSAP 3 Express. I've got over 6 hours of training and loads of exclusive demos to help you master the GreenSock Animation Platform from the ground up at creativeCodingClub.com As always, I load my videos up with info so that I don't have to write a ton of stuff, but here are some key points. Get ScrollTrigger and GSAP ScrollTrigger is hosted on a CDN along with GSAP. Just use the script tags below to load it into your page. <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.4.0/gsap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.4.0/ScrollTrigger.min.js"></script> Register ScrollTrigger It's recommended to register ScrollTrigger in your JavaScript to avoid tree-shaking with build tools. gsap.registerPlugin(ScrollTrigger); You can get recent CDN Urls from the GSAP Overview in the docs. For use with npm or more advanced build tools check out the GSAP installation videos. Super Basic Demo with a Single Tween The animation is super slow so that you can see how the animation reacts to entering and leaving the scroller-start and scroller-end positions. See the Pen ScrollTrigger QuickStart by Snorkl.tv (@snorkltv) on CodePen. Control a Timeline with ScrollTrigger See the Pen GreenSock ScrollTrigger Timeline by Snorkl.tv (@snorkltv) on CodePen. GreenSock's Toggle Action Demo In the video I explained how toggleActions work and how important they are. For each toggle event (onEnter, onLeave, onEnterBack, onLeaveBack) you can assign an action (play, pause, restart, reset, resume, complete, reverse, none). You'll assign a toggleAction via a 4-part string like "restart pause resume reverse". The best way to understand how they work is to play with the values in the demos above and study the demo below. See the Pen toggleActions - ScrollTrigger by GreenSock (@GreenSock) on CodePen. I'm hoping these resources help get you up and running quickly. For more inspiration check GreenSock's massive collection of ScrollTrigger Demos. What's next? I've only scratched the surface of what ScrollTrigger can do. I'll definitely be creating more training on this awesome tool. If you need help learning GSAP and want to take your skills to the next level check out my courses at CreativeCodingClub.com.
  25. className: "+=active" just remove all class's and so on https://codesandbox.io/s/affectionate-cookies-9hccc
×