Jump to content
Search Community

SplitText menu help

popflier test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hi @popflier :)

 

Yes you can add tweens to a timeline with add(), but in this case, that is not what the "part2" is doing. It's a position parameter label. I wanted both of those tweens to start at the same time so I used the label. More info about the position parameter can be found here:

https://greensock.com/position-parameter

 

In addition to labels, the add() method does allow you to add tweens, timelines and callbacks to the timeline. Yes they will play in sequence unless you add the position parameter. @Carl has an excellent article about creating timelines in functions and returning them to a master timeline with add(). 

https://css-tricks.com/writing-smarter-animation-code/

 

The "#image" target in that tween is indeed targeting #image1, #image2 and #image3 as it loops. You'll see that we have the index of the loop (i) in there? On the first iteration of the loop i has a value of 0 so we add 1 to that (i+1) which we then concatenate with the string "#image" and the result is "#image1". That's just one way of doing it. You don't even need the IDs on the images. We could get a node list and use that in the tween too.

 

// get the elements
var thePics = document.querySelectorAll(".image");

// this tween would do the same thing
tl.to(thePics[i], tl.duration(), {opacity:1}, 0);

 

I only used the IDs to show another option as I had already added an array option in one of the other tweens.

 

tl.to(theTarget, 0.5, { backgroundColor:colors[i], ease:Linear.easeNone }, "part2");

 

That little index is quite handy for many things when you're looping. Hopefully that makes sense. Happy tweening.

:)

 

  • Like 5
Link to comment
Share on other sites

Thanks Craig for explaining all of that to me. I forgot about concatenation so now the indexing makes sense. 

 

Finally...my question that I said I would get back to earlier! :)

 

Going back to my last question, " How can I target all of the other links in the menu aside from the one being clicked on? "

I realized your hierarchy solution would work in many cases. However, I don't know that it will work for what I am trying to do. The reason being that when a link is clicked on my menu I want to have that link remain visible and I want for the other links in the menu to fade out. When I tried to use the hierarchy method all of the links end up fading out, including the one clicked.  I tried to pseudo code what I am ultimately trying to do, which I detailed below. I think I  have to figure out how to:

1) target all links but the one being clicked other than using the hierarchy method.

2) how to kill a hover event

3) understand how I can reverse an animation on a specific timeline when I am using multiple timelines in my menu.

 

I think I just have to figure out how to do these 3 things and I can put this menu together.

 

Once the main menu link has been clicked I want to kill() the main menu hover script because the clicked link doesn't stay the dark red like I want. If you move your mouse off or over the clicked link again. The hover script activates and the colors change. I don't want that to happen. I want the clicked link to remain the color I've stated in code already and remain in the shifted position that happens on hover (x:-20.)  I'm wanting to follow the below pseudo code in this order: (I imagine all of this pseudo code would go inside a main menu click event)
      1) if  $".menuLinks" is clicked
      2) turn the clicked link to #731012 and remain at the x:-20 position that it's in
      3) kill() the .menuLinks.hover code so it won't activate if you move your mouse off of the clicked link
      4) then fade out all of the other main menu links that were NOT clicked
      5) then reverse the line of code below (this is for the socialLinks animation on the left:)
      
     

tl.staggerFrom(charsSocial, 0.30, { opacity: 1, scale: 0.01, y: 0, rotationY: 360,  ease:
SteppedEase.config(20) }, 0.05);


      
      6) finally, reverse the "navMenu" animation below (this is the same code from the initial animation sequence but needs to be in reverse)
      
     

 tl.fromTo(navMenu, 1, { y: -450 }, { ease: Back.easeOut.config(1.2), y: 0 });


      
      Then I'm trying to do a similar thing with the Social Links on the bottom left except it would be:
      1) Turn the clicked link into a solid color
      2) kill () the hover animation on the socialLinks
      3) fade out the other socialLinks NOT clicked
      4) reverse the menuLinks animation code below:
      
     

tl.staggerFrom(charsMain, 0.62, { opacity: 1, scale: 0.01, y: 0, rotationY: 360, ease: Back.easeOut }, 0.05);


      
      5) finally, reverse the "navMenu" animation below (this is the same code from the initial animation sequence but needs to be in reverse)
      
     

 tl.fromTo(navMenu, 1, { y: -450 }, { ease: Back.easeOut.config(1.2), y: 0 });

 

 

Here's everything that I have so far:

See the Pen EpZywp by popflier (@popflier) on CodePen

 

The CLOSE button is another issue that I am trying to work out on a separate pen.  I'm just trying to get the entire "X" to rotate on hover and reverse it's initial loading timeline animation on click. Seems so easy...not!  Here's the pen for that. (I put some comments in the JS code too.)

 

See the Pen pZapLB by popflier (@popflier) on CodePen

                                                                                                                                                                                                                                                                                     

Link to comment
Share on other sites

I'm not sure I followed all that, but hopefully this is what you needed.

 

You can use jQuery's not() method to target all the elements except the one you clicked.

http://api.jquery.com/not/

 

To remove the hover you can look into the off() method.

http://api.jquery.com/off/

 

You don't necessarily need to reverse a timeline to make the elements exit. You can create a new timeline in the click handler to make them exit. You could also create multiple timelines outside of the click handler and just play() when needed. Lots of ways to make it happen really. Here's a fork of your demo.

 

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

 

I'm not understanding the question about the close button. Your pen is targeting a variable called 'x' on line 23, but I don't know what that is. I'd need some more details about the desired outcome to be of any help on that part.

 

Happy tweening.

:)

 

  • Like 2
Link to comment
Share on other sites

Thank you very much for your assistance (once again!)

 

Your forks helped me to get the link code the way that I wanted, but more importantly to understand a lot more about how Greensock works.  For example, I didn't realize you could place an array in the code like this. I understand how the += works in relation to time but I don't understand why you used it here for the rotation?

 

tlRotate.to([line01, line02], .35, {backgroundColor: "#ddd", rotation:"+=180"});

 

I created a new fork based on the one you had made here below. For some reason when I tried to combine the close button code into this fork the hover and click events for the close button no longer work and I'm not sure why? I tried using the code without any edits and it didn't work at all. I've now edited the code the click event the way I wanted it with the idea that when clicked the close button goes away (like an on/off button) and the whole navMenu fades out. That's at least what I'm trying to get to happen in the code I wrote.

 

See the Pen JBwyYK?editors=1010 by popflier (@popflier) on CodePen

 

Thank you so much for your generous time and assistance with this entire menu.

nicole

 

 

 

Link to comment
Share on other sites

The hover and click didn't work because you have the .xBtn class z-index set to -50. Change that and the hover and click work just fine. There is one error in the exitAnim() function. The tween on line 118 is missing the duration. (You also wouldn't want that timeline paused.) Here's a new fork of your pen with those changes.

 

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

In answer to your question about the +=180 for the lines: I used that because you said you wanted the x shape to rotate 180 degrees on hover. Those lines have already rotated several times so rather than try to figure out an exact rotation it's just easier to rotate 180 degrees from their current location.

 

Hopefully that helps. Happy tweening.

:)

 

  • Like 2
Link to comment
Share on other sites

<<The hover and click didn't work because you have the .xBtn class z-index set to -50. Change that and the hover and click work just fine. >>

 

I am so glad that I asked you about this because I absolutely would never  have figured out that this was the issue. I obviously only copied the JS and not the CSS from your pen.

 

<<There is one error in the exitAnim() function. The tween on line 118 is missing the duration.>>

 

My thinking in doing that was I thought that if I left the duration off that it would default to 0.

 

<<(You also wouldn't want that timeline paused.) Here's a new fork of your pen with those changes.>>

 

I'll be honest. I'm still trying to figure out the callbacks. I usually have to add and remove them just to see how it affects the timeline, but I've been researching them in the docs.

 

<<In answer to your question about the +=180 for the lines: I used that because you said you wanted the x shape to rotate 180 degrees on hover. Those lines have already rotated several times so rather than try to figure out an exact rotation it's just easier to rotate 180 degrees from their current location.>>
 
Okay, so that's how you do that! I kept trying to find a way to append or join the those two lines. I must have tried 50 different lines of code and spent hours researching it. I knew there must be a simple way to do it...and there was.   :)
 
I'm pretty sure that I've got it from here on this menu, which I am sure that you must be ecstatic about since you've spent so much time helping me with this. I need to do some timing tweaks an make a few other adjustments but I'm confident that I can finish it on my own.
 
Thank you so so very much for your time and assistance. I greatly appreciate it! I have a couple of other things to put together so I'm sure it won't be the last time I post a question  :)
  • Like 1
Link to comment
Share on other sites

What? We're done with this one already? ;) :D

 

I was happy to help and I'm glad it's coming together for you. If you need additional GSAP assistance on this or any other projects, we're happy to help. Thank you for your support with your membership in Club GreenSock. It's most appreciated. Happy tweening.

:)

 

  • Like 2
  • Haha 2
Link to comment
Share on other sites

  • 2 weeks later...
On 8/12/2018 at 2:42 PM, PointC said:

What? We're done with this one already? ;) :D

 

I was happy to help and I'm glad it's coming together for you. If you need additional GSAP assistance on this or any other projects, we're happy to help. Thank you for your support with your membership in Club GreenSock. It's most appreciated. Happy tweening.

:)

 

 

Okay, I lied....but not intentionally  :) I swear I thought this was finished (!!!) and while it is I can't figure out how to integrate it into my site. :( I need to have a separate button that is not part of this navMenu trigger the menu sliding down. I added "paused: true" to the first timeline in the sequence so that prevents it from automatically running it. However, the three issues I have are:

 

1) How can I setup the "menu" button in the pen so that it will have the navMenu we created slide down from the top and go through it's animation sequences?

 

 2) As you can see the overlay/navMenu is still taking up space but isn't visible. The navMenu has pushed the header menu button I added further down the page instead of that button being at the top. How can I keep the menu button at the top so when it is clicked it triggers this navMenu we created? I want the navMenu to "overlay" any content that might be on the page and not push that content down the page. Does that make sense?

 

3) How would I adjust my click function on my "X" close button in my navMenu to close out the navMenu and make sure the menu button I created slides back to the top again?

 

Here's the updated pen:

 

See the Pen zJxMRX by popflier (@popflier) on CodePen

 

Sorry Craig...I really thought I was done with this.  :(

 

Link to comment
Share on other sites

 

7 hours ago, popflier said:

1) How can I setup the "menu" button in the pen so that it will have the navMenu we created slide down from the top and go through it's animation sequences?

 

To get the timeline to play(), you need to add an event listener to your new text menu button.

 

7 hours ago, popflier said:

 2) As you can see the overlay/navMenu is still taking up space but isn't visible. The navMenu has pushed the header menu button I added further down the page instead of that button being at the top. How can I keep the menu button at the top so when it is clicked it triggers this navMenu we created? I want the navMenu to "overlay" any content that might be on the page and not push that content down the page. Does that make sense?

 

 

By setting the height of the nav to auto instead of 100% you can hide it up top. (You could also use 450px in this case.) You could add the new text button to the nav and it would go along for the ride. Or you could add a tween that moves that new button 450px at the same time as the main nav.

 

7 hours ago, popflier said:

3) How would I adjust my click function on my "X" close button in my navMenu to close out the navMenu and make sure the menu button I created slides back to the top again?

 

 

 Adding a tween to the exit animation will take that menu button back to the top.

 

Keep in mind though that you're setting the autoAlpha of everything to 0 in your exitAnim so if a user closes the menu without clicking a link, the menu will not work correctly the second time they click the menu button because everything is hidden. You'll have to decide what to do about that. You could move the menu back up to y:-450 at the end of the exit timeline and set the autoAlpha back to 1. Or you could use fromTo() tweens. Or you could set the autoAlpha at the beginning of the entry timeline. You'll also have to tween your new button when someone clicks a link.

 

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

 

 Hopefully that helps. Happy tweening.

:)

 

  • Like 2
Link to comment
Share on other sites

Thinking about it and working on this for the last two days, I thought it would just be easier to create a toggle menu button instead of having the other menu button I created to initiate the animation on click.  Not using Greensock, I was able to create a simple toggle button that when pressed overlays a main menu navigation. However, when I try to integrate that code with Greensock I can't get it to work properly. I think part of my issue may be with scope(?), which is why I keep declaring the same vars and timelines throughout the code.

 

The things that seem to work correctly are:

 

1) The initial page loads correctly with just the hamburger menu button in the top right corner.

2) When the menu button is clicked the menu drops down and seems to load correctly.

3) The menu button animates to an "X" like it should.

4) When the menu button is pressed again the "X" animates back to the hamburger button.

 

From this point on nothing else works and I am not 100% why that is. I keep thinking I need some If /else statements to fix some of it, but when I try and implement that code it doesn't work. (there's some code in my pen that's been deactivated so you can see what I mean about these.) I tried creating separate functions to work after links are clicked to reset the alpha and opacity but it's not working. I'm just really frustrated. I've spent nearly 200 hours trying to figure out how to get it to work and I'm no closer. I'm about ready to just say forget it and use the non-animated toggle code I created and just use that menu instead.

Maybe you see something in the pen that's an easy fix?

 

See the Pen OoVQmY by popflier (@popflier) on CodePen

 

 

Link to comment
Share on other sites

hmmm... sorry to hear that you're getting frustrated. I can certainly understand how projects can get overwhelming. It's perhaps a good idea to take a step back and just get certain pieces and concepts working. I'll get to that in second. 

 

I took a quick look at your new version and the thing that jumped out immediately are the timelines on lines 62 and 118. You have those reversed and they shouldn't be set that way. Sometimes you want to reverse a timeline when you create it, but not in this case.

 

You do have a complex project here. By that I don't mean the animations are too complicated, but there are many things the user could do. Someone could try to close the menu while it's animating into view. You can click a main link while the social links are animating. The menu could be closed without selecting a link. Those are just a few of the many possible scenarios. You're also targeting the same elements in different timelines so you have to decide how to reset them should they need to be targeted by a different timeline. All this is certainly doable. You just have to figure out the logic to control all possible outcomes. I find putting pen to paper and drawing a little flowchart of user interaction can help. 

 

Okay, now looking at this in small bites, I'd start with the concept of not allowing (or allowing) user interaction while pieces are animating. Take a look at this simple demo:

 

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

Try clicking the menu button while the animation is playing. You'll see you can click as often as you like and the menu animation will just keep reversing each time you click. 

 

Now look at this version.

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

Try the same thing. You'll see that the timeline will not reverse while it's playing. I've used the isActive() method to prevent anything from happening. You could also set a toggle variable to prevent clicks/hovers at certain times/events. It doesn't really matter how you check things, but this is an important concept in a project like yours as you have many moving pieces and multiple user click/hover scenarios. Can animations/timelines be interrupted? 

 

My recommendation to get you on track for this project would be to comment out all the SplitText animations and logic for now. Just focus on bringing the menu into view and listening for a click on the social/main links. Ask yourself, will you allow a click or hover before everything has animated into view? What happens if a user closes the menu without selecting a link? Once you get that set, you can start turning on the SplitText animations and controlling the click logic with a toggle or the isActive() method. 

 

I think you can get there if you just take a step back and look at it piece by piece. You're not really starting over. You're just turning off certain things while you make logic decisions. Make sense?

 

Happy tweening.

:)

 

  • Like 2
Link to comment
Share on other sites

  • 2 months later...

I have not given up on this navigation menu and have been working on it for months. One day I will get it to work. That being said, I could really use some help answering a few questions because no matter what I have tried I do not understand why the code doesn't work in places the way I think  it should. Here are the questions that I cannot figure out right now. There will be more I'm sure later.

 

I have tried breaking things into sections like you recommended. I get one thing working but then when I try to integrate it with other code it no longer works like expected. I haven't gotten to the clicked link animations yet, which is why I have them disabled. I need to figure out why these first parts do not work first.

 

Here is the main pen that I am working with now:

See the Pen vVaYJZ?editors=0110 by popflier (@popflier) on CodePen

 

1) The  .menuContainer and .socialContainer visibility. These classes need to be hidden until the menu button is pressed. When the menu is closed and after a link is clicked there is a set of animations that run. Once those complete the containers need to be hidden  I have tried this a thousand ways, but it's still not working correctly.

 

  • I have set CSS visibility on these classes to hidden, changed it to visible on menu click, and changed back to hidden when the menu button is closed or a link is clicked. Doesn't work.
  • I have tried using an if/else statement on the animationIndex so that when the index is 0 the containers are hidden and when the index is 1 the containers are shown. Doesn't work.
  • I have tried adding / removing the classes entirely. Only sort of worked but it was very glitchy.

 

2) I cannot get the animations to restart if the menu button is clicked to open a second time. I was able to get this to work using this code that I had found on another Greensock pen, but once I tried to integrate it into my main pen with the other animations it no longer worked. I like the idea of setting up the open/close animations in an index like this. I just can't get it to work right.

 

See the Pen vVRWrQ?editors=1010 by popflier (@popflier) on CodePen

 

3) I am still struggling to get the "isActive" code to work on any of the animations. I have tried a thousand different ways to get it to work so that when any animations are running the user is not able to click on anything until ANY currently running animations first complete.

 

  • I have tried so many different ways to do this that it's not even funny. For example, this code for the menu link hovers. Why doesn't this work so that a hover animation first has to complete before another hover animation will begin?
  • Why are my hover animations so glitchy?
$(".menuLinks").each(function(i, element) {
    var tlLoad = new TimelineMax({ paused: true, reversed: true });
    var targets = $(this).find("div");
    var menuLoad = tlLoad.staggerTo(targets, 0.25, { color: "#7b9898", x:-20, rotationY: 360, ease: Back.easeOut }, 0.03);


$(element).hover(mainHover, mainHover);
    function mainHover() {
   
    if(!menuLoad.isActive()){
    menuLoad.reversed(!menuLoad.reversed())
     
    if (!tlLoad.reversed() ) {
       tlLoad.play();
    } else {
       tlLoad.reverse();
     }
         }
    } 

 

 

I would greatly appreciate any help with these questions. Thanks in advance.

 

 

Link to comment
Share on other sites

Looks like the project has changed a little bit since I last saw it. 

 

1. Using visibility: hidden on those containers should work fine. The problem is the way you're trying to assign the new visibility. To use jQuery's CSS method you'd need to do this.

 

$(".menuContainer").css('visibility', 'visible')

 

The way you have it structured now, you're just assigning the string "visible" to the setViz variable. It's not doing anything to the menu elements. My recommendation for this part would be to use GSAP to set() it.

 

TweenMax.set(".menuContainer, .socialContainer", {visibility:"visible"})

 

You should also get rid of the CSS transition on line 65. You don't want to cause a fight between CSS and GSAP. ;)

 

2. The timeline is restarting just fine on subsequent clicks. The problem is your 'close' timeline is animating all the letters to an opacity of 0 and random x/y positions. You then run your 'open' timeline again and use from() tweens. That is animating those elements from the positions you want, but they're landing where they were at the end of the 'close' timeline. Plus they're at an opacity of 0 so you can't see them anyway. To see what's happening, please try setting the opacity to 0.5 on the two loops on lines 88 & 92. Now open and close the menu a few times. See what's happening? You'll either need to set() those elements back where you want them or use fromTo() tweens in your 'open' timeline. My recommendation would be the latter.

 

3. isActive() can be a bit tricky when you have multiple timelines to check. In cases like that I like to set a global variable to either true or false if I'm allowing new clicks. Here's an example from another thread, but it should give you the idea.

 

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

 

Hopefully that helps. Happy tweening.

:)

 

  • Like 2
Link to comment
Share on other sites

Thanks Craig.  Yes, I changed the menu slightly. I was having issues getting the menu to dropdown on click so I changed it to the way that it is now. Pretty much everything else is the same except for the way the menu closes if someone doesn't click on a link.

 

I see now what you were saying about the timeline restarting. I changed the opacity and could then see the issue. I was able to get the containers to become visible/hidden using this code you suggested:

 

if (iconTL.reversed()) {
    iconTL.play(); 
    TweenMax.set(".menuContainer, .socialContainer", {opacity: 1, visibility:"visible"});
  } else {
    iconTL.reverse();
    var fade = new TimelineMax();
    fade.to(".menuContainer, .socialContainer", 1, {opacity:0, ease: Back.easeOut}, .8);
    TweenMax.set(".menuContainer, .socialContainer", {visibility:"hidden", delay: 1.5});
  }

 

I wanted the text characters to fade out when the menu was closed and not just have it be abrupt so I added a timeline to fade it and then set it to hide the container. This seems to work ok.

 

I also changed the CSS transition for the hover like you suggested to avoid conflicts with GSAP:

 

TweenMax.set("#span1, #span2, #span3", {backgroundColor:"#cd2026"});

 

I did the same for the hover off. That works now, but this is where the good new ends.  :(

 

In regards to resetting the timeline you said: "You'll either need to set() those elements back where you want them or use fromTo() tweens in your 'open' timeline. My recommendation would be the latter. "

 

I still cannot get this to work. I've tried a number of different lines of code both inside and outside of the click event but nothing seems to work in order to set the animation back to it's starting point. I tried doing .set and staggerFromTo but when I do that the menu completely freezes and no longer opens at all. What am I doing wrong?

 

I see what you're saying about the global variable for isActive. I set it up similar to how you did in your pen. I can't tell if it's working because like I mentioned in my previous post my hover animations are glitchy and I don't understand why that is. There must be some conflicting code but I can't seem to find it.

 

I'm sure that you thought I gave up on this menu, but I haven't. I took your earlier advice and broke everything up into sections. It all fell apart again once I tried integrating the code together with the different pieces. I'm not giving up on it until it works :)  Thanks for any assistance.

 

 

 

 

Link to comment
Share on other sites

I didn't see any fromTo() tweens on either the open or close timelines. Here's an approximation of what you're trying to do.

 

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

 

See how the timelines contain fromTo() tweens? IMHO that's the best way to handle it when you have multiple timelines targeting the same elements. That way things don't get stuck somewhere and every element starts and ends where you'd expect. Be sure you're targeting all the necessary properties too.

 

You'll also see I added an isActive() check in each button handler. The close timeline can't play if the open is active and vice versa.

 

Make sense?

 

Happy tweening.

:)

 

PS There's no need to split your text and declare your variables twice. Not that it's hurting anything. It's just unnecessary. 

 

  • Like 2
Link to comment
Share on other sites

Thank you very much for the example. This helped me so incredibly much! I have been working on this for hours since you posted this example. I've finally figured it out. I had originally put in "staggerFromTo" tweens in my previous pen. I couldn't get them to work and I didn't understand why so I removed them, which was why you didn't see them there. I looked at the Docs but they didn't help me to understand why they were not working. After seeing your example I realized that I was not actually coding the fromTo tweens correctly. I now understand how those tweens work because of your example. Thank you for doing that.

 

The full pen that I am working from currently is here:

See the Pen BqXayZ?editors=1010 by popflier (@popflier) on CodePen

 

I still have to figure out the following on this menu: 1) isActive() on initial menu load, 2) how to target the splitText characters when a main menu link is clicked 3) isActive() when mainMenu hovers are active 4) how to reset menu after a link is clicked

 

(Is that all? I really hope so for my sanity...)

 

1) isActive() on initial menu load;

While the isActive makes sense on your example, I can't figure out how to get the isActive() to work with a toggle button. I tried placing the playOpen function in the toggle click and using an if/else like this:

 

$("#toggle").click(function(playOpen){
  
if (iconTL.reversed()) {
    iconTL.play(); 
    TweenMax.set(".menuContainer, .socialContainer", {opacity: 1, visibility:"visible"}, "-=.5");
  } else {
    iconTL.reverse();
    var fade = new TimelineMax();
    fade.to(".menuContainer, .socialContainer", 1, {opacity:0, ease: Back.easeOut}, .8);
    TweenMax.set(".menuContainer, .socialContainer", {visibility:"hidden", delay: 1.5});
   }
  
if ( animationIndex === "0") {
    TweenMax.set(".menuContainer, .socialContainer", {visibility:"visible"})
} else if ( animationIndex === "1") {
    TweenMax.set(".menuContainer, .socialContainer", {visibility:"hidden"})
};

  animationIndex = ++animationIndex % 2;
  console.log(animationIndex); 
  animations[animationIndex].restart();

   function playOpen(e) {
     e.preventDefault;
     if (!close.isActive()) {
       open.play(0);
     } else if (!open.isActive()) {
       close.play(0);
     }
 };

 

That didn't work so I tried placing the playOpen and playClose functions inside the if/else if animationIndexes like this:

 

$("#toggle").click(function(){
  
if (iconTL.reversed()) {
    iconTL.play(); 
    TweenMax.set(".menuContainer, .socialContainer", {opacity: 1, visibility:"visible"}, "-=.5");
  } else {
    iconTL.reverse();
    var fade = new TimelineMax();
    fade.to(".menuContainer, .socialContainer", 1, {opacity:0, ease: Back.easeOut}, .8);
    TweenMax.set(".menuContainer, .socialContainer", {visibility:"hidden", delay: 1.5});
   }
  
if ( animationIndex === "0") {
    TweenMax.set(".menuContainer, .socialContainer", {visibility:"visible"})
    playOpen();
} else if ( animationIndex === "1") {
    TweenMax.set(".menuContainer, .socialContainer", {visibility:"hidden"})
    playClose();
};

  animationIndex = ++animationIndex % 2;
  console.log(animationIndex); 
  animations[animationIndex].restart();
  
});

function playOpen() {
  if (!closeAnim.isActive()) {
    openAnim.play(0);
  }
}

function playClose() {
  if (!openAnim.isActive()) {
    closeAnim.play(0);
  }
}

 

That didn't work either. I also tried putting the playOpen and playFrom functions directly into the if/else if animationIndex statements instead of calling "playOpen();" and "playClose();". 

 

Why do none of these work?

 

2) How to target the splitText characters when a main menu link is clicked

My goal after a main menu link is clicked is for the following to happen:

  1. The link that has been click would change color.
  2. ALL of the OTHER links that were not clicked on both the main menu and the social media menu would "dissolve" or "blow apart" (just like they already are when you click on the toggle button to close the menu.)
  3. I will have another animation happen to the link that was clicked after the rest of the links "blow apart." I'm still figuring out what I want it to do here.

I have tried already to do this a couple of different ways but I cannot get it to work. I have tried creating another animationIndex that would have the timeline for a link clicked and the animations that would happen to the links not clicked and a second timeline that would reset the menu. I've been focusing on just trying to get the first timeline to work and not the reset timeline.

 

var mainClick = new TimelineMax ({paused: true});
var mainReset = new TimelineMax({paused: true});
var mainIndex = -1;
var mainAnimations = [mainClick, mainReset];
$("#toggle").click(function(){
 
// if ( mainIndex === "0") {
     
// } else if ( mainIndex === "1") {
    
// };

  mainIndex = ++mainIndex % 2;
  console.log(mainIndex); 
  mainAnimations[mainIndex].restart();  
});

var splitText = new SplitText(".menuLinks", { type: "chars" });
var charsMain = splitText.chars;
var socialSplit = new SplitText (".socialLinks", {type: "chars"});
var charsSocial = socialSplit.chars;


  $(".menuLinks").each(function(i, element) {
    var targets = $(this).find("div");
  
 $(element).click(toDo);
    function toDo(e) {
      e.preventDefault;
      // for the link clicked //
      
      $(".menuLinks").off();
 }
      mainClick.staggerTo(targets, 0.5, {color: "#731012", x:-120},"menuClick",.05);

      for (let i = 0; i < charsMain.length; i++) {
  mainClick.to(charsMain[i].not(this), 1,{ x: Math.random() * 400, y: Math.random() * -400, scale: Math.random() * 2, opacity: 0}, Math.random(),"menuClick");
}
 
});

 

This code will allow the clicked link to change color and move -120 in the X direction but I cannot seem to target the characters for all of the other links  that were not clicked so that I can essentially "blow them apart" like in the closing button animation. How can I target the characters for these other links? I also tried not putting these two timelines in indexes but that didn't work either so I deleted that code.

 

3) isActive() when mainMenu hovers are active

I basically just want the user not to be able to click on a link until the hover animations have completed. I was trying to do something like this with the note that I have in the code below, but I don't know how to write it. I think it would work if I knew how to write that line of code.

 

////////////////////  MAIN MENU AND SOCIAL LINK HOVER ANIMATIONS  //////////////////////////

var splitText = new SplitText(".menuLinks", { type: "chars" });
var charsMain = splitText.chars.length;
var socialSplit = new SplitText (".socialLinks", {type: "chars"});
var charsSocial = socialSplit.chars.length;

    $(".menuLinks").each(function(i, element) {
    var mainHover = new TimelineMax({ paused: true, reversed: true });
    var targets = $(this).find("div");
      
   mainHover.staggerFromTo(
  targets, 0.15,
  { color: "#cd2026", opacity: 1, rotationY: 0, x: 0},
  { color: "#7b9898", opacity: 1, rotationY: 360, x: -20, ease: Back.easeOut},
  0.03
);

//////////////////////////// MAIN MENU LINK HOVERS ////////////////////////////
    $(element).hover(mainHovers, mainHovers);
    function mainHovers() {
    
      
  if (!mainHover.isActive()) {
    //then do not allow a link to be clicked until the mainHover timeline has completed//
  }

    if ( mainHover.reversed() ) {
       mainHover.play();
    } else {
       mainHover.reverse();
    }
   }
  });

 

Last but not least...

 

4) How to reset the menu after a link is clicked

This one I have been trying to figure out for months. I know that once the menu is on the site that when a link is clicked it would load that page and essentially would reload the menu. However, if this were coded for a React app , which I may do, then I would need the menu to be able to be reset after a link is clicked. This is a function that I know I will need in other areas of my final site but I don't know where to start. Like I said earlier, I tried using an index for playing a link and resetting the menu but I couldn't get the first part of that theory to work so I didn't try getting the second half of that theory to work. Would even doing an index like this work? Are there any pens that you can point me to for examples as to how this might need to work?

 

Thanks so much for your assistance with this!

 

 

 

Edited by popflier
Forgot to add the link to the pen
Link to comment
Share on other sites

1. isActive()  Since you have so many timelines and animations that could be running, you may want to just use a global variable to allow/disallow clicks instead of isActive(). I mentioned it earlier in this thread, but here's a really simple example. I've used a canAnimate variable and a status variable to approximate what you have happening in your project with things being open or closed. This also avoids the animationIndex variable that you increment with some of your clicks.

 

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

 

2. Target all other links except the one that was clicked. There are many ways to do this. Earlier in the thread I think I showed you how to use jQuery's :not selector. Another way to handle this would be get the children of the siblings and animate those divs.

 

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

 

3. Main menu isActive() - see #1 above

 

4. When you want to reset everything, there would be a number of ways to do it. You could seek() the progress() of the various timelines, you could set() the elements where you need them. You could also use clearProps().

https://greensock.com/docs/Plugins/CSSPlugin#clearProps

 

As with all things GSAP (or JavaScript in general) there are many paths to the same destination.

 

Happy tweening.

 

  • Like 3
Link to comment
Share on other sites

Thanks again for the pen examples and explanations. Just to clarify...

<<1) ..." This also avoids the animationIndex variable that you increment with some of your clicks. ">>

 

What do you mean exactly by "...avoids the animationIndex variable...?"

 

I had tried to setup a canAnimate variable before when you mentioned it earlier in the thread. I think I didn't understand how to do this exactly, but this example makes more sense to me.

 

<<2. Target all other links except the one that was clicked. There are many ways to do this. Earlier in the thread I think I showed you how to use jQuery's :not selector. Another way to handle this would be get the children of the siblings and animate those divs. >>

 

Yes, I was trying to do this like you had showed me with the :not selector, but I was having trouble with it in conjunction with the splitText chars. I know that you created this example specific to my project to help me understand about how to use children/siblings. I greatly appreciate that. I hope others will find it useful. The one question I had was that after one of these links are clicked and the others disappear via the opacity: 0 attribute, those links are obviously still there...just not visible. How can I truly remove them while still keeping the clicked link visible? I tried adding an onComplete type of variable to run after the link letters have flown off to set the visibility of those links to hidden, but that didn't work. Why?

 

function flyAway() {
  TweenMax.to($(this), 1, { color: "#42a6e0", ease: Linear.easeNone });

  letters = $(this)
    .siblings()
    .children();
  for (let i = 0; i < letters.length; i++) {
    TweenMax.to(letters[i], random(1, 2), {
      x: random(-200, 200),
      y: random(-200, 200),
      scale: random(0.5, 2),
      opacity: 0,
      delay: random(0, 0.25)
    },"finished");
  }
  
  function finished () {
    TweenMax.to(letters[i],{
      visibility: "hidden"
    });
  }
}

 

4. When you want to reset everything, there would be a number of ways to do it. You could seek() the progress() of the various timelines, you could set() the elements where you need them. You could also use clearProps().

https://greensock.com/docs/Plugins/CSSPlugin#clearProps

 

I'll look into all of these. I'll probably have questions later about this but I've bookmarked and will return to this once I get some of the other elements working. Thank you!

 

Link to comment
Share on other sites

It looked to me like your animationIndex variable was/is being incremented on click and then you use the modulus operator to see if it's odd or even. I assumed that was to set things to either visible or hidden. I was just saying that a variable with a value of either open or closed would negate the need for the animationIndex. I personally find it easier to check if a variable is open/closed, yes/no, true/false (or whatever you like) than to keep incrementing something on click and finding out if the click is odd or even. If you're using it for something else that I'm not understanding or just want to keep using it, feel free. That was just my two cents worth.

 

In answer to your question about hiding the links, there are a few things to correct. First, I think you may be confusing how to call an onComplete function with the position parameter or the onCompleteAll in a stagger tween. The way you have that written won't call the finished function. You'd write it like this:

 

  for (let i = 0; i < letters.length; i++) {
    TweenMax.to(letters[i], random(1, 2), {
      x: random(-200, 200),
      y: random(-200, 200),
      scale: random(0.5, 2),
      opacity: 0,
      delay: random(0, 0.25),
      onComplete: finished
    });
  }

 

But that will still cause problems for two reasons. 

1. The variable i will be undefined in the finished() function.

To solve this, you could target this.target in the tween.

2. You're using a .to() tween to set the visibility, but you have no duration.

To solve that, you'd use a set() tween.

 

So you could write it like this.

 

  function finished () {
    TweenMax.set(this.target,{
      visibility: "hidden"
    });
  }

 

The good news is none of that is even necessary. To hide the links after they fade out, you'd simply use autoAlpha instead of opacity.

 

function flyAway() {
  TweenMax.to($(this), 1, { color: "#42a6e0", ease: Linear.easeNone });

  letters = $(this)
    .siblings()
    .children();
  for (let i = 0; i < letters.length; i++) {
    TweenMax.to(letters[i], random(1, 2), {
      x: random(-200, 200),
      y: random(-200, 200),
      scale: random(0.5, 2),
      autoAlpha: 0,
      delay: random(0, 0.25)
    });
  }
}

 

autoAlpha is the same as opacity with one exception. Once the opacity hits 0, the visibility property is set to "hidden".

 https://greensock.com/docs/Plugins/CSSPlugin#autoAlpha

 

I've updated my pen to use autoAlpha.

 

 

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

 

Happy tweening.

 

PS When you're calling functions it's quite helpful to add a console.log() to the function to make sure it's working. 

  • Like 1
Link to comment
Share on other sites

I understand what you're saying about the onComplete function. Yes, I was confused between the two, but I understand now what you're saying.

 

Regarding hiding the other links that were not clicked. I had wanted to do this so that a user couldn't run their mouse over where the text links used to be before they were hidden so that no one could still be able to click on any of them AFTER they had already clicked a link.  For example, if you click on a link in your pen the other links flyaway and leave you with one. If you move your mouse over the location where any of the links used to be prior to flying away you can still click on them. I thought that if I used visibility: hidden that it would hide the link but still allow the space that the link took up to affect the layout, no? If I used display: none then shouldn't it theoretically remove all other links, other than the one clicked, from the layout? 

 

<< autoAlpha is the same as opacity with one exception. Once the opacity hits 0, the visibility property is set to "hidden". >>

 

I couldn't get it to work using any of these properties either in the tween or the .set. So how can you remove these other hidden links so users cannot click on them?

 

<< PS When you're calling functions it's quite helpful to add a console.log() to the function to make sure it's working.  >>

 

You're right. They taught us to do this in my 3 month full stack MERN certification course and I've just gotten lazy about using it.  :)  (and yes, javascript has always been difficult for me to comprehend.)  :(

Link to comment
Share on other sites

If you look back at this thread on August 8, you’ll see that I told you about removing event listeners with jQuery’s off() method. I assumed you were using that and you mentioned something else would be happening to the menu after a click so I wasn’t concerned about the users ability to click again. Here’s another version of my demo with the off() method applied and changing the cursor back to default.

 

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

 

Keep in mind that none of this removes the divs from the page. SplitText creates a collection of divs from the letters which are all children of the original element.

 

10 hours ago, popflier said:

 (and yes, javascript has always been difficult for me to comprehend.)  :(

 

If JavaScript is still confusing for you right now, it may be worth your time to go back and do some additional training and practice. At the very least, it may be advisable to dial back your expectations on this menu for now. I think I mentioned earlier in the thread that this is an ambitious project with multiple timelines, hovers and possible interactions to monitor. For now, maybe just have the menu slide into view and the letters blow apart on click. You could add all the hover animations and isActive() checks when you’re more comfortable with everything. Maybe you won’t even want all the hover animations since they’ll be problematic on touch devices. Just my two cents worth. YMMV

 

Happy tweening

  • Like 3
Link to comment
Share on other sites

  • 3 weeks later...
On 11/4/2018 at 8:10 AM, PointC said:

<<If you look back at this thread on August 8, you’ll see that I told you about removing event listeners with jQuery’s off() method. I assumed you were using that and you mentioned something else would be happening to the menu after a click so I wasn’t concerned about the users ability to click again. Here’s another version of my demo with the off() method applied and changing the cursor back to default.>>

 

Yes, you're right. I was using the .off () method.

 

In regards to doing a reset you said earlier:

 

Quote

<< When you want to reset everything, there would be a number of ways to do it. You could seek() the progress() of the various timelines, you could set() the elements where you need them. You could also use clearProps(). >>

 

I looked into seek() and progress() and have been working with a fork of the last pen that you made. I figured that if I could get your pen to reset then I could apply the same logic to my menu.

 

That being said, I can't get the menu to reset entirely in your pen and it's also doing some very strange things if I try and create/use a timeline as opposed to TweenMax. Of course, I don't understand why this is causing it to do what it's doing. I tried to do a reset using seek and progress first with just using TweenMax and then with creating a timeline. I grayed out what I had tried to do in the fork I made of your pen so you could see what I had done and failed at. I also tried using .add and .addLabel in combination with everything and that didn't work either. I even tried using restart() and pause(1). I setup an onComplete function for testing so I know the animation is getting access to that, but even if I use progress or seek in the onComplete it doesn't work.  I looked through the forums and the docs and those posts suggest using seek() or pause(1).  What am I missing?

 

Here's my fork:

See the Pen mQyEQe?editors=1010 by popflier (@popflier) on CodePen

 

<< If JavaScript is still confusing for you right now, it may be worth your time to go back and do some additional training and practice. At the very least, it may be advisable to dial back your expectations on this menu for now. >>

 

I've been enrolled and taken so many Udemy classes on JS and gone through the University bootcamp course and I still struggle with js.  GSAP and three.js make more sense to me than vanilla js for some reason. I wish there was a Udemy GSAP course one of you guys could create. For me personally, I learn better from watching someone do it and explain why they are doing what they are doing as they go. I know that I'm never going to be a JS developer. I just really want to build my portfolio site and integrate GASP into it myself.

 

happy thanksgiving!

Link to comment
Share on other sites

You're on the right track with pause(). 

 

One problem is you have the onComplete callback on each tween in the loop. Sometimes you may want that, but I think in this scenario you don't want anything to reset until the whole timeline is done, right? In that case, you need the onComplete on the timeline. What's currently happening in your demo is the first tween on the timeline fires the onComplete call and you seek(1). The timeline is then playing from 1 second and that same tween fires the onComplete again. And so on... None of the additional targets will ever animate. At that point, you're stuck in a loop.

 

The other issue is you're rebuilding the timeline on each click, but all the all tweens are still there from the last click. Just pausing a timeline doesn't clear the old tweens so when you add more, they just get added to the end. You can clear() the timeline in your onComplete to fix that. 

 

I'm not sure if you wanted to animate the letters one by one, but your other animations had them all fly apart as a group so you can add the position parameter to each tween in the loop to fix that. 

 

What you need to do is pause() the timeline back at 0 and then clear() it. Also in the onComplete you can add the listeners back to the links and switch the cursor back to a pointer. I also added a little indicator to tell you the duration() of the timeline on each click. See how when the onComplete fires and the timeline is cleared the duration goes back to 0?

 

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

 

Hopefully that helps. Happy tweening and Thanksgiving.

 

  • Like 1
Link to comment
Share on other sites

  • 3 months later...

@PointC time to open this old boy of a thread up again :D Last question I promise lol!

 

I'm working on the following roll over text effect which I really like. Problem is there is about 50 lines of code doing what you could do in a few which is making it really slow.

 

I know there is a cool way of looping through with something like this... but how do you do that with split text as you need to access each group of characters separately.

 

How would I do that?

 

let headingsA = [
  ".video-title-1",
  ".video-title-2", 
  ".video-title-3",
  ".video-title-4",
  ".video-title-5", 
  ".video-title-6"
];

    
let headingsB = [
  ".video-title-1b",
  ".video-title-2b", 
  ".video-title-3b",
  ".video-title-4b",
  ".video-title-5b", 
  ".video-title-6b"
];  


var splitText1 = new SplitText(headingsA[i], {type:"words,chars"}),
    splitChars1 = splitText1.chars;

var splitText1b = new SplitText(headingsB[i], {type:"words,chars"}),
    splitChars1b = splitText1b.chars;

 

See the Pen zbwYMM by smallio (@smallio) on CodePen

 

Cheers!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...