1

I want to move away from jQuery for animation so I have been using GSAP. I am trying to figure out how to fire multiple animations on an element and its children. Basically I want to give the #navicon a "720 cork" effect which is working fine and a fade/toggle the icon to the children of this #navicon container which is not working at all.

If I was using jQuery only, I would have probably just add multiple classes as needed and use them to trigger some CSS3 transforms. However, GSAP seems to be really fast.

I have read the GSAP docs pretty thoroughly. And I see how to chain tweens with "timeline" but I am not sure how to fire multiple tweens on different elements based on one event.

Here is my code so far:

var toggleMobiMenu = function() {
    $('#navicon').on('click touchstart', function() {
        TweenMax.to($(this), 0.5, { rotationY: 720, rotationX: -720 })
            .to($(this).find('#open'), 0.5, { opacity: 0 })
            .to($(this).find('#closed'), 0.5, { opacity: 1 });
    });
}
toggleMobiMenu();

and here is the fiddle of the same. Does anyone know how to tween all these 3 elements at once?

A.L
  • 10,259
  • 10
  • 67
  • 98
HelloWorld
  • 2,480
  • 3
  • 28
  • 45
  • hey @HelloWorld, did my suggestion below help? – Tahir Ahmed Jun 22 '15 at 14:08
  • @TahirAhmed I ended up solving the problem another way, but thanks for catching my stupid mislabeling of '#navicon-open' and 'navicon-closed'! – HelloWorld Jun 22 '15 at 16:48
  • I think you missed to read the **Snippet** part of my answer where I have mentioned **`TimelineMax`** ;) – Tahir Ahmed Jun 22 '15 at 18:14
  • Because in your solution, I believe you are still not making the most of it. You are creating a new instance of **`TimelineLite`** upon every click. Instead you should have one pre-defined instance that you only play *forward* or *backward*. – Tahir Ahmed Jun 22 '15 at 18:20
  • Plus, you seem to be only *adding* to the animation queue of a timeline using the **`to`** method where as, as stated above, there should actually be only one timeline instance already defined outside the scope of the click handler and only utilized within. – Tahir Ahmed Jun 22 '15 at 18:26
  • And lastly, instead of using a flag to know animation direction, you can utilize **`TimelineMax`** very own **`reversed()`** property. – Tahir Ahmed Jun 22 '15 at 18:31
  • Take a look at my **Snippet** below again which addresses the issues I just raised. And let me know if you have any questions. – Tahir Ahmed Jun 22 '15 at 18:33
  • @HelloWorld there is really no need to use `this` and `find()` if you are targeting a selector ID. You should only have one element with that specific ID on your web page anyway. An `ID` is a unique identifier so if you have multiple ID's with the same ID you need to make them unique. Plus targeting just the ID is faster without `this` and `find()` .. so just use `.to('#open', 0.5, { opacity: 0 })` and `.to('#closed', 0.5, { opacity: 1 });` – Jonathan Marzullo Oct 07 '15 at 19:02

1 Answers1

3

Two problems in your code:

  • The method to of TweenMax is a static method but what it returns is an instance of TweenMax. Read more about the difference between static and instance methods here and this is basically a language agnostic concept. Since, in this case, the instance does not have a to method available to it as per the docs, your code breaks.
  • Second problem with the code is that you are using find() method to find #open and #close elements inside #navicon element when clicked, but as per your HTML structure, there are no such things as #open and #close elements. Instead you have #navicon-open and #navicon-close elements. Putting them instead of the old ones should fix that.

So all in all, your code should look like this:

var toggleMobiMenu = function() {
    $('#navicon').on('click touchstart', function() {
        TweenMax.to($(this),0.5,{rotationY:720,rotationX:-720});
        TweenMax.to($(this).find('#navicon-open'),0.5,{opacity:0});
        TweenMax.to($(this).find('#navicon-close'),0.5,{opacity:1});
    });
}
toggleMobiMenu();

But if I understand it correctly, what you are really trying to do is to come up with an animation that moves forward or backward i.e. toggles every time the icon is clicked. So I have reworked the code in the snippet below provided you an idea of just that:

Snippet:

var navIcon=$('#navicon');
var navIconOpen=$('#navicon-open');
var navIconClose=$('#navicon-close');
var timeline=new TimelineMax({paused:true,reversed:true});
var duration=.6;
var ease=Power2.easeOut;
var rotation=360;
var init=function(){
    timeline.to(navIcon,duration,{rotationY:rotation,rotationX:-rotation,ease:ease},0);
    timeline.to(navIconOpen,duration,{opacity:0,ease:ease},0);
    timeline.to(navIconClose,duration,{opacity:1,ease:ease},0);
    navIcon.on('click touchstart',function(){
        toggleMobileMenu();
    });
};
var toggleMobileMenu=function(){
    timeline.reversed()?timeline.play():timeline.reverse();
};
//
init();
#navicon {
 height:45px;
 width:45px;
 border:#000 3px solid;
 border-radius:50%;
 margin:5px 35px 0 0;
 position:relative;
 float:right;
}

#navicon i {
 color:#000;
 top:8px;
 left:11px;
 font-size:24px;
 position:absolute;
}

#navicon #navicon-open {
 opacity:1;
}

#navicon #navicon-close {
 opacity:0;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/TweenMax.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<a id="navicon" href="javascript:void(0);">
    <i id="navicon-open" class="fa fa-bars"></i>
    <i id="navicon-close" class="fa fa-times"></i>
</a>

Hope this helps.

Community
  • 1
  • 1
Tahir Ahmed
  • 5,687
  • 2
  • 17
  • 28