Jump to content
GreenSock

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

Rodrigo last won the day on May 2

Rodrigo had the most liked content!

Rodrigo

Moderators
  • Posts

    2,105
  • Joined

  • Last visited

  • Days Won

    168

Community Answers

  1. Rodrigo's post in Problem with ScrollTrigger timeline onComplete was marked as the answer   
    Hi and welcome to the GreenSock forums.
     
    The issue is that right now you're executing the function, so as soon as the browser gets to that part of the code the playSound function is executed.
     
    GSAP has an excellent callback system that allows you to pass parameters, set scope, etc. This should work as expected:
    tl.to("#knapp", { background: "#a6a6a6", onComplete: playSound, onCompleteParams: ["knapp0"] }); Here you can learn more about callbacks, just scroll down to the Special Properties section:
    https://greensock.com/docs/v3/GSAP/gsap.to()
     
    Happy Tweening!!!
  2. Rodrigo's post in Horizontal scrolltrigger to sections (React.js) was marked as the answer   
    Hi,
     
    This should be the easiest/simplest setup for the codepen @Cassie linked in a React app:
     
    https://codesandbox.io/s/lively-sunset-9ifwq?file=/src/App.js
     
    Happy Tweening!!!
  3. Rodrigo's post in ScrollTrigger snap to section with normal functional scroll bar (without triggering sections) was marked as the answer   
    Hi and welcome to the GreenSock forums.
     
    It seems to me that the Tesla site is not using the same approach of the codepen. Basically the site checks different events (mouse wheel, keyboard, etc) and scrolls the entire viewport to a specific section of the page. Also if you move scroll down mid-section using the scroll bar and then use an event, it also behaves a bit weird.
     
    Honestly, if I was using that approach I'd remove the scroll bar and follow the code used in this samples by @PointC:

    See the Pen MzWzyv by PointC (@PointC) on CodePen

    See the Pen YRzRyM by PointC (@PointC) on CodePen
     
    Happy Tweening!!!
  4. Rodrigo's post in Batch and DrawSVG together was marked as the answer   
    Hi,
     
    In the first codepen each number it's inside a different <svg> tag, therefore when you loop through each SVG container, you're basically looping through each number at a time. Based on your code you should add all three numbers in the same <svg> tag and add the data-stagger attribute to them. Another option is to give those particular svg elements a unique class in order to loop through them independently from the rest and add a stagger based on the index value of the current iteration.
     
    Finally, as I understand that it might take longer and not be the most elegant solution, in cases like this I prefer to create my animations for each section in their own code block. Sure, creating a single loop for everything is simpler and shorter, but as you already found out, it comes with a few drawbacks. Since you have some similar sections (the wavy line) you can loop through those, but for the rest my advice is to create an independent code block for each.
     
    Happy Tweening!!!
  5. Rodrigo's post in I just joined the GSAP community and have some questions about using it with react! was marked as the answer   
    Hi,
     
    The virtual DOM React uses it's something that a developer hardly will access at any given point in an app development. I haven't seen a single case of that. For more info read this: https://reactjs.org/docs/faq-internals.html
     
    The usage of refs is not something we came up with here in the GSAP forums, it's the way React allows developers to access the DOM elements rendered in a specific component, nothing more. The samples, again, are pretty clear in the React documentation, you can use the useRef() hook as mentioned here: https://reactjs.org/docs/refs-and-the-dom.html#refs-and-function-components. You can also use a ref callback in functional components, but always using the useRef() hook as the container of the reference:
    const myRef = useRef(); const createRef = (element) => { myRef.current = element; }; return ( <div ref={createRef}> </div> ); This is also handy if you're using an array.map() helper and want to store multiple refs in an array:
    const myArray = [/* Array Elements */]; const Component = () => { const myRefs = useRefs([]); // by default an empty array const createRef = (element, index) => { myRefs.current[index] = element; }; return ( <ul> {myArray.map((el, index) => { <li key={`myEl-${index}`} ref={() => createRef(el, index)}> </li> })} </ul> ); };  
    That depends on the app being build. The amount of useEffect hooks in a component should go in hand with the properties in the state and/or props being passed to the component, that are being updated. You should be able to infer that from the app's context. Not the context API, but what is actually happening in the app, what is being updated and why is important to keep track of that.
     
    Normally the best approach is to store your GSAP instances in a useRef hook in order to keep them through re-renders and make it easier to kill them when the component is unmounted. In case of a re-render the animation should continue without any issues. Keep in mind that React only replaces the part of the DOM that has to be replaced in a re-render, otherwise it would be extremely expensive and inefficient. If the DOM node being updated in a re-render is actually being animated when the component's state or props are updated, the updated element would be rendered in the position given by the original styles and the GSAP instance would not break, because GSAP will keep a reference to the DOM element's object  and will keep updating it. In this cases the best approach is to use an useEffect hook to kill the animation and create a new one with the re-rendered element, but this is a rare scenario.
     
    This depends on how you plan to control the animations. If you need to control the animation of a child component in a parent one, use forwarding refs: https://reactjs.org/docs/forwarding-refs.html, otherwise keep the GSAP instances in the component where they happen, it makes more sense.
     
    Yeah, that depends on the implementation of your app. If layout effect solves the issue then is a good idea to use it. So what's the issue you mention with the layout effect hook? If you're already implementing it, I don't understand the premise of your question.
     
    Mhhh... how exactly can you use GSAP for mounting or unmounting components? GSAP works with DOM nodes by updating some properties in a specific amount of time or frames (when you use frames). It has no control on when a React component is mounted/unmounted. Why we suggest transition group? Because transition group, as well as Vue's <transition> component are based on Angular's ng-animate, which is an excellent way to control animations in components. Transition group actually handles the mount/unmount process in a way that allows to create animations for that process and, while it certainly has a few open issues in github, is currently actively maintained by the React team and many very talented developers. Finally I've used transition group in production, in many projects without any issues and I've seen in it used in plenty of projects that are highly praised and without bugs or glitches as you mention. If you're running into a particular issue, perhaps you could provide a reduced live sample in codesandbox to take a look and also report such bugs to the React team: https://github.com/reactjs/react-transition-group/issues
     
    Yep, indeed that is quite outdated and I haven't had time to update this guide. While React suggest to use the functional approach, there is no real issue in using classes, in fact React Router, not exactly a shady library, uses classes: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Router.js. Also plenty of other libraries that work without any issues on top of React, still use class based components. There is actually no hard evidence that functional components are better than class based components. You could argue that the code is better organized or something like that, but I've seen apps that are a mess in both approaches. The fact that the React team favors the use of functional programming over class programming is just a preference and nothing more. In fact GSAP uses classes and I think it works pretty good right?
    https://github.com/greensock/GSAP/blob/master/src/gsap-core.js#L1133
     
    Happy Tweening!!!
  6. Rodrigo's post in React.js Continuous horizontal text animation was marked as the answer   
    @BrianCross Is right, you only have one element in your marquee, so is kind of hard to make it work like that.
     
    Also you're not including the modifiers plugin in order to create the endless animation. I made a simple example for this:
     
    https://codesandbox.io/s/gsap-endless-marquee-l5tv4
     
    Finally, I haven't used the react-gsap package, so I'm using the regular approach to use GSAP in a React project. Since that is not a GSAP official project we don't have enough time to offer support on how to use it correctly, but based on what I can see, it shouldn't be too complicated. Although I simply prefer the traditional way.
     
    Happy Tweening!!!
  7. Rodrigo's post in Page transition with TimelineMax to another page was marked as the answer   
    Indeed, just keep it there, outside the viewport and bring it in using GSAP like the sample in the other thread you mention.
     
    Happy Tweening!!!
  8. Rodrigo's post in Timeline Reverse not working in React with GSAP 3 was marked as the answer   
    Hi and welcome to the GreenSock forums.
     
    There are a few things that are causing the issue.
     
    You're adding instances to the timeline inside a useEffect() hook that is called every time the menu is toggled, so basically you're creating the timeline over and over again. The first time the timeline takes the elements and update their styles to what you want, by the second time the timeline is created and it updates the styles to the indicated values, but in the first run the timeline already set those values in the elements, so nothing happens. In this type of situations (toggle animations) is better to move all the code that adds animations to a timeline, to an useEffect hook that runs only in the first render, using an empty dependencies array. Then store the timeline in a specific reference in order to keep it through future re-renders. Finally handle the timeline toggle inside a specific useEffect hook. This seems to be doing what you want:
    const tl = useRef(gsap.timeline({ defaults: { ease: "power2.inOut" } }).reverse()); const [isMenuOpen, ToggleMenu] = useState(false); useEffect(() => { tl.current.to([activatorRef.current], { background: "#805ad5", borderRadius: "0 5em 5em 0" }); tl.current.to( [navItemContainerRef.current], { clipPath: "ellipse(100% 100% at 50% 50%)" }, "-=.5" ); tl.current.to( [navItemIconRefs.current], { opacity: 1, transform: "translateX(0)", stagger: 0.5 }, "-=.5" ); }, []); useEffect(() => { tl.current.reversed(!isMenuOpen); }, [isMenuOpen]); Happy Tweening!!!
  9. Rodrigo's post in GSAP animation is breaking on refresh (ReactJs) was marked as the answer   
    Hi,
     
    Your problem could be here:
    let tl = new TimelineLite({ delay: 0.8 }); useEffect(() => {}, [tl]); You're creating your timeline as a variable in the root scope of the component's function, that will not be kept through re-renders. Assuming that this is a header and you might be using router, every route update there could be a re-render. Also you're passing tl as a dependency in your hook's array, but tl is not a state value or a prop , so that code will run every time the state or a prop is updated.
     
    Use an empty array in the useEffect() hook and store a reference to the timeline using useRef():
    const tl = useRef(gsap.timeline({ paused: true })); useEffect(() => { tl.current // All your gsap instances here .from() }, []); Try that and let us know how it goes.
     
    Happy Tweening!!!
  10. Rodrigo's post in React : Do i have to register gsap.registerPlugin(ScrollTrigger); in every component? was marked as the answer   
    As Brian points, basically you're killing all the ScrollTrigger instances you have.
     
    Also your set up a is a little bit funky, IMHO.
     
    If I was you I'd create the ScrollTrigger instance on each component in the useEffect() hook, passing an empty array to run the code only in the initial render and store it in a constant or a ref if you prefer. In the same hook, use the cleanup function to kill that specific ScrollTrigger instance, something  like this:
    const myScrollTrigger = useRef(); useEffect(() => { myScrollTrigger.current = gsap.to(contentRef.current, { scrollTrigger: { trigger: triggerRef.current, start: "top center", end: "bottom center", scrub: true, markers: true, }, yoyo: true, repeat: 1, opacity: 1, y: 0, }); return (() => { myScrollTrigger.current.kill(); }); }, []); Of course you have to keep in mind the trigger element and pass that either as a prop or perhaps context, depending on the depth of your component's tree.
     
    Happy Tweening!!!
  11. Rodrigo's post in React.js/GraphQL Slider with Gsap Animations? was marked as the answer   
    Hi and welcome to the GreenSock forums.
     
    Definitely you can use GSAP to animate your content slider. In fact two of our superstars have created amazing slider samples.
     
    This one by @Chrysto

    See the Pen kDvmC by bassta (@bassta) on CodePen
     
    This one by @PointC

    See the Pen YRzRyM by PointC (@PointC) on CodePen
     
    As an advice your starting point should be to create refs for each slide and use a useEffect hook in order to go to the target slide when the state is updated. Finally instead of using all sorts of calculations use xPercent in order to move the element to the desired direction, xPercent basically moves the target element based on it's size. In this case if a slide is 800px width and you usexPercent: -100 the slide will move 800px to the left, if you use fluid width it will use whatever width the element has, it's a great trick for responsive animations. Just make each slide to use all the available height and width of it's container and that such container has an overflow: hidden of course.
     
    If you have any issues with your GSAP approach, feel free to create a reduced live sample in Codesandbox in order to take a better look at it.
     
    Happy Tweening!!!
  12. Rodrigo's post in Can't refresh scrollTrigger after layout change was marked as the answer   
    Hi,
     
    You should update your ScrollTrigger instances, once the collapse animation is completed, not when the state that triggers such animation has changed:
    const openState = { height: "auto", duration, onComplete() { ScrollTrigger.refresh(true); } }; const closedState = { duration, delay, height: 0, overflow: "hidden", onComplete() { ScrollTrigger.refresh(true); } }; React.useEffect(() => { if (isCollapsed) { gsap.to(ref.current, closedState); } else { gsap.to(ref.current, openState); } }, [isCollapsed]); Happy Tweening!!!
  13. Rodrigo's post in In Nuxt.js, need to refresh between pages, for Scrolltrigger to work was marked as the answer   
    Hi and welcome to the GreenSock forums.
     
    This most likely has to do with the fact that your ScrollTrigger instances could be still alive when you switch from one page to the other. Just follow the regular hooks that Vue has for components life cycle. Keep in mind that a Nuxt page is a Vue component after all. Create all your ScrollTrigger and GSAP instances in the mounted hook and pause and kill all your instances in the beforeDestroy hook. Something like this:
     
    export default { mounted() { this.tl = gsap.timeline({ /* Configuration Here */ }); }, beforeDestroy() { this.tl.pause().kill(); }, head() { return { title: "Home", }; }, }; If you're still having issues, please try to create a reduced live editable sample in codesandbox using the Nuxt template, showing just the barebones of your app in order to identify what the problem could be.
     
    Happy Tweening!!!
  14. Rodrigo's post in Update React State via Timeline was marked as the answer   
    Hi and welcome to the GreenSock forums.
     
    There are a few issues with the code you posted.
     
    First, you're wrapping all your relevant code inside a single useEffect hook, which depends on the value of the state property intensity. The problem here is that, if you want to update the value of intensity using a GSAP instance, you can't create and run that instance inside a hook that is called when the same value is updated. You can easily create a bug that will start an infinite loop or a potential huge memory leak. Use a useEffect hook with an empty dependencies array in order to run that only when the component is mounted. Also don't run the registerPlugin method on a hook that will be ran several times, there is no need for doing that.
     
    Second, try to create and store your GSAP instances and ScrollTrigger instances using the useRef hook in order to create instances that will persist throughout re-renders. Right now every time the intensity value is changed you'll end up re-creating the GSAP instance, which might not be necessary, same thing with the ScrollTrigger instances. Also this allows you to easily kill your instances when the component is unmounted during the cleanup stage.
     
    Third, state values are meant to be updated only by their corresponding callback, that's the whole reason why the useState hook creates two elements the variable holding the state value and a callback that updates such value. With this tl.to(intensity, { value: setIntensity(0.5) }) basically you're telling GSAP to update something that already has a method to be updated. You can update the value of a dummy object and using an onUpdate callback you can pass the setIntensity method and the value being tweened as the new state value:
    gsap.to({value: 1.5}, { value: 0.5, onUpdate: setIntensity, onUpdateParams: [value] }); Finally, for what I see in your code, you're not really using the intensity value anywhere else in your code. You're only passing it as a prop to the blob component, so that's another reason to remove it as a dependency in your useEffect hook.
     
    As you mentioned a reduced live editable sample in codesandbox would prove very helpful to understand what you're trying to do. No need to set up the whole THREE code, since it seems to be irrelevant to the question at this point, just a simple one describing what you're trying to achieve.
     
    Happy Tweening!!!
  15. Rodrigo's post in React Draggable Picker was marked as the answer   
    Hi,
     
    Right now I don't have a lot of time to dive into this, but taking a quick look at your code and Blake's sample there are a few things I spotted. First the approach you're using to set the initial position of each element is not working, as every element is above it's parent container. Second the proxy element that Blake uses as target of the Draggable instance is an actual DOM node, in your case you're using an object, which is not working.
     
    If I was you I'd first manage to position the elements correctly. Then create and successfully run the animations to move the elements up and down. Finally create the Draggable instance to actually manage those animations.
     
    Happy Tweening!!!
  16. Rodrigo's post in Scroll Trigger breaking using React Router was marked as the answer   
    Hi,
     
    The useEffect() hook can return a function that is executed when the component is unmounted (something React Router does for you), in that function you have to kill your ScrollTrigger instances in order to prevent that type of issues, something like this:
    useEffect(() => { // All your code here return () => { // Cleanup here, kill your ScrollTrigger instances here }; }, []); I don't have a live sample to show right now. I'll try to make something simple during the weekend. Hopefully this will be enough to get you started right now.
     
    Happy Tweening!!!
  17. Rodrigo's post in Using GSAP with VueJS 3 Composition API was marked as the answer   
    Hi and welcome to the GreenSock forums.
     
    Keep in mind that the setup method in the composition API runs before the component instance is created and it's purpose is to store the component's reactive data. In your particular case title is just a reference to a reactive data, nothing more. Is not a DOM node that GSAP can actually tween in the App. What you could do is create a reference that later in the component's lifecycle, can hold a GSAP instance, but it seems overkill IMHO.
     
    The recommendation for using GSAP with Vue is to attach a GSAP instance to the component's instance in the mounted hook and use refs in the template to identify the DOM node you want to use, like this:
    <template> <div ref="myElement" /> </template> Then in the script tag:
    import { gsap } from "gsap"; export default { mounted () { this.myTween = gsap.to(this.$refs.myElement, { /* GSAP Config Here */ }); } } Keep in mind that the main purpose of the composition API is to avoid giant monolithic reactive setups in large applications, or smaller ones that need a scalable flexibility, but it shouldn't be a place to define your GSAP instances.
     
    Happy Tweening!!!
  18. Rodrigo's post in Clean up "old animation" on window resize? (React) was marked as the answer   
    Hi,
     
    In the same useEffect() hook that you're using to create the new animations, before doing that, kill all the animations that will be created again. For this I would recommend a factory function that will kill and then re-create all the animations that will be affected by the resize event.
     
    With that in mind is always a good idea to store your animations in a ref using the useRef() hook in order to make it simple to access to them and create them again. This also ensures that the animations are not affected by re-renders that are caused by other reasons.
     
    Something like this:
    const isResized = useSelector(state => state.isResized); const myTween = useRef(null); useEffect(() => { // Kill tween first myTween.current.kill(); // Create the tween again createMyTween(); }, [isResized]); const createMyTween = () => { myTween.current = gsap.to(/* GSAP config here */); } Happy Tweening!!!
  19. Rodrigo's post in Using Splittext with vue.js was marked as the answer   
    Hi and welcome to the GreenSock forums.
     
    SplitText is a Club GreenSock plugin, so you need to purchase a membership to download it and use it, or reference it in your NPM installation. That's why webpack is throwing that error, basically you're importing something that is not in the GSAP package installed in your app.
     
    After you become a member you can use it in your projects. In the meanwhile there are "open" versions of the Club's plugins that you can use in Codepen and Codesandbox, so you can try the plugins, see how they work and be completely sure about becoming a member. You can check them here:
     

    See the Pen OPqpRJ by GreenSock (@GreenSock) on CodePen
     
    Jut copy the link, go to Codesandbox, create a free account, create a new Sandbox, select either a Vue or Vue3 app and in the external resources tab (in the sidebar) and paste the link for the SplitText plugin. Then in your <script> tag, simply create a reference to it and register the plugin. Here is a live example that follows that pattern:
     
    https://codesandbox.io/s/l261n378km?file=/src/App.vue
     
    The only difference is that this sample uses the ScrambleText plugin instead of the SplitText plugin, but the procedure is the same.
     
    Happy Tweening!!!
  20. Rodrigo's post in Is using useLayoutEffect some sort of last resort for gsap if animation doesn't work as expected was marked as the answer   
    Hi,
     
    I wouldn't call useLayoutEffect a last resource kind of thing, is just a tool provided by React for certain scenarios. In this cases I don't use .from() instances, which undoubtedly are very convenient, and just create the initial state using CSS and then use a regular .to() instance to avoid that initial render, specially with modals, alerts, toasts and/or whatever other name they have .
     
    Now if useLayoutEffect is working as you expect, then you have your solution!!! If it ain't broken don't fix it, some people would say 
     
    Happy Tweening!!!
  21. Rodrigo's post in Gsap CDN in React was marked as the answer   
    Hi,
     
    The main issue here is, while codesandbox can let go the gsap reference here:
    class Circle extends Component { constructor(props) { super(props); this.circle = null; this.tl = gsap.timeline(); // this gsap reference } componentDidMount() { this.tl.to(this.circle, { x: 250, duration: 5, repeat: -1 }); } render() { return <div ref={(div) => (this.circle = div)} className="ball"></div>; } } Keep in mind that is never defined anywhere in the file, so other setups with more strict linting could crash. When you use the CDN links the gsap constructor is added to the global scope, in this case the window object. This can be solved by simply creating a constant in order to actually have a definition for such reference:
    const gsap = window.gsap; class Circle extends Component { constructor(props) { super(props); this.circle = null; this.tl = gsap.timeline(); } componentDidMount() { this.tl.to(this.circle, { x: 250, duration: 5, repeat: -1 }); } render() { return <div ref={(div) => (this.circle = div)} className="ball"></div>; } } With that the issue should be solved.
     
    Happy Tweening!!!
  22. Rodrigo's post in gsap animation cleanup in vuejs was marked as the answer   
    Actually no, since you're not using the instance elsewhere, also, as I said before, at that point you have to take into account what Vue will do after the component is destroyed/unmounted, which could possibly release everything to garbage collection. Honestly I don't have the slightest idea of how Vue handles garbage collection, but I'm pretty sure that is done the right way, otherwise no one would use Vue.
     
    Having a reference in the code is close to mention or remember it, soto speak. I'm going to get a little grim here, sorry. Let's say that you have a plant and that plant dies, then you put it in the garbage can so is collected by the truck. If you keep talking about the plant or remembering the plant, that's a reference to the plant, so even with the plant being gone, is still there. If you never mention or remember the plant ever again in your life, is like every trace of it was erased the moment it went into the trash can.
     
    This is a super simplified example of keeping a reference. We create a GSAP instance, we play it and then we don't need it again in our app, so we kill it, but if there is another method that uses the instance, even if it was killed before, there is a reference to it. In that case kill() stops the animation and releases it to garbage collection, but the browser's garbage collector won't release it because, at some point that method could be called so the instance is not released from memory. If you kill the GSAP instance and there is no longer used in the app after it, then is taken by garbage collection and released. Here is a simple explanation of how garbage collection works in JS:
    https://www.geeksforgeeks.org/garbage-collection-in-javascript/
     
    This code creates and completely removes the GSAP instance:
    mounted: function() { // We create the GSAP instance, which is now allocated in memory this.tween = gsap.to(this.$refs.element, {/* config */}); }, methods: { killTween: function () { // Kill the tween this.tween.kill(); }, } There is no other reference to this.tween so it's released by GSAP and the garbage collector sees that and also sees that there is no other reference to it in the code, so the memory allocation is released as well.
     
    This code doesn't remove the GSAP instance:
    mounted: function () { this.tween = gsap.to(this.$refs.element, {/* config */}); }, methods: { killTween: function () { // Kills the tween this.tween.kill(); }, reuseTween: function () { // Here is another reference to the GSAP instance this.tween.restart(); }, }, Since the instance is referenced elsewhere in the code, kill() stops the animation and releases it to garbage collection, but garbage collector sees the other reference, so it doesn't release the allocated memory even if you never call that method in the app lifetime.
     
    Finally don't worry too much about garbage collection and all this stuff as is a complete universe on it's own. Seriously garbage collection in every language is something that could constitute a career in on itself, what I just explained to you here is basically everything I know on the subject, and believe me there is a lot more about this. Just be sure to not have unnecessary and unused references and/or methods in your code and you'll be fine, since Vue, GSAP and the browser will handle the rest for you.
     
    Happy Tweening!!!
  23. Rodrigo's post in ReactJS, ScrollTrigger, ScrollToPlugin - react-router-dom issue was marked as the answer   
    Hi and welcome to the GreenSock forums.
     
    The problem is that the ScrollTrigger instances that you created are still listening to the scroll event in the window object. When you navigate to another route these instances still exists (actually if you scroll up/down in the /partner route, you can see that the scroll is completely messed up). Then you navigate back to the home route and a completely new set of ScrollTrigger instances is created yet again, which make things even more complicated. What you have to do is kill the existing ScrollTrigger instances when the component is unmounted and then it works as expected. Just add this to the end of the useEffect() hook in the Home.js component:
     
    return () => { ScrollTrigger.getAll().forEach((instance) => { instance.kill(); }); // This in case a scroll animation is active while the route is updated gsap.killTweensOf(window); }; As a recommendation, don't use regular query selectors if you can avoid it. Also store your GSAP instances in variables or in an object (whatever works better for you) in order to make it easier to clean up your component when is unmounted.
     
    https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup
     
    Happy Tweening!!!
  24. Rodrigo's post in adding controller class to control playback example was marked as the answer   
    Hi,
     
    It's working for me when I declare the  GSAP instance before the wheelnav. Keep in mind that JS reads the entire code before it's executed, saving variables into memory to access them later. Perhaps the issue comes when clicking on the text element of the pie-nav?. I see that it has no effect whatsoever, perhaps the developers didn't consider event handlers in the text or tspan tags. But clicking on the green part (the path tag) always triggers the function regardless of where you declare the GSAP instances. If you remove the text you'll see that it works:
    <div id='piemenu' data-wheelnav data-wheelnav-slicepath='DonutSlice' data-wheelnav-marker data-wheelnav-markerpath='PieLineMarker' data-wheelnav-rotateoff data-wheelnav-navangle='270' data-wheelnav-cssmode data-wheelnav-init> <div data-wheelnav-navitemtext=' '></div> <div data-wheelnav-navitemtext=' '></div> <div data-wheelnav-navitemtext=' '></div> </div> Also a good way to avoid such issues is to use an immediately invoked function expression (IIFE), like that you can be completely sure that everything will be read before being executed and avoid any possible conflicts. When working with jQuery I use the following:
    (function($){$(function(){ var animlogo = $("#animlogo"),     tween = TweenLite.to(animlogo, 6, {left:"90%", ease:Linear.easeNone});   // declare wheelnav var piemenu = new wheelnav('piemenu'); piemenu.clockwise = false; piemenu.wheelRadius = piemenu.wheelRadius * 0.83; piemenu.createWheel(); piemenu.navItems[0].navSlice.mouseup(function () {    //alert('PLAY');    tween.play(); }); piemenu.navItems[1].navSlice.mouseup(function () {    //alert('PAUSE');   tween.pause(); }); piemenu.navItems[2].navSlice.mouseup(function () {    //('RESET');   tween.restart(); }); });}(jQuery)); That basically covers everything, avoids conflicts and has the document.ready as well.
     
    Give that a try and  let us know.
  25. Rodrigo's post in Passing variable into timeline via play? was marked as the answer   
    Well if you want to delay the start of the entire timeline and not just a few tweens in it, you could use shiftChildren(), although after you used it you'll have to remove that time if te user clicks on the button to play it immediately.
     
    Another option is to create a function and pass a time parameter and use a delayed call to start the timeline:
    var tl = new TimelineLite(); function startTl(delay){ TweenLite.delayedCall(delay, function(){tl.play();}); } And with the other button just use tl.play()
×