Jump to content
GreenSock

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

Animation only working once with multiple elements and timelines

Recommended Posts

Hello,

 

I have a map with different elements and I have created a menu so you can show/hide the element types you want. 

 

This is the code:

$('.interactivo .default-container .menu ul li a.menu-citizen').each( function(){
      this.tl2 = new TimelineMax({paused:true});
      this.tl2.to(".elements", 0, {autoAlpha:1});
      this.tl2.to(".smart-green .elements, .smart-mobility .elements, .smart-water .elements, .smart-safety .elements, .smart-efficiency .elements", 0, {autoAlpha:0});

  $(this).click(function(){
    if( $(this).hasClass('active') ){
      $(this).removeClass('active');
      this.tl2.reverse();
    }else{
      $('.interactivo .default-container .menu ul li a').removeClass('active');
      $(this).addClass('active');
      this.tl2.play();
      }
  });
});

$('.interactivo .default-container .menu ul li a.menu-water').each( function(){
      this.tl3 = new TimelineMax({paused:true});
      this.tl3.to(".elements", 0, {autoAlpha:1});
      this.tl3.to(".smart-citizen .elements, .smart-green .elements, .smart-mobility .elements, .smart-safety .elements, .smart-efficiency .elements", 0, {autoAlpha:0});

  $(this).click(function(){
    if( $(this).hasClass('active') ){
      $(this).removeClass('active');
      this.tl3.reverse();
    }else{
      $('.interactivo .default-container .menu ul li a').removeClass('active');
      $(this).addClass('active');
      this.tl3.play();
      }
  });
});

$('.interactivo .default-container .menu ul li a.menu-mobility').each( function(){
      this.tl4 = new TimelineMax({paused:true});
      this.tl4.to(".elements", 0, {autoAlpha:1});
      this.tl4.to(".smart-citizen .elements, .smart-green .elements, .smart-water .elements, .smart-safety .elements, .smart-efficiency .elements", 0, {autoAlpha:0});
  $(this).click(function(){
    if( $(this).hasClass('active') ){
      $(this).removeClass('active');
      this.tl4.reverse();
    }else{
      $('.interactivo .default-container .menu ul li a').removeClass('active');
      $(this).addClass('active');
      this.tl4.play();
      }
  });
});

$('.interactivo .default-container .menu ul li a.menu-green').each( function(){
      this.tl5 = new TimelineMax({paused:true});
      this.tl5.to(".elements", 0, {autoAlpha:1});
      this.tl5.to(".smart-citizen .elements, .smart-mobility .elements, .smart-water .elements, .smart-safety .elements, .smart-efficiency .elements", 0, {autoAlpha:0});
  $(this).click(function(){
    if( $(this).hasClass('active') ){
      $(this).removeClass('active');
      this.tl5.reverse();
    }else{
      $('.interactivo .default-container .menu ul li a').removeClass('active');
      $(this).addClass('active');
      this.tl5.play();
      }
  });
});

$('.interactivo .default-container .menu ul li a.menu-efficiency').each( function(){
      this.tl6 = new TimelineMax({paused:true});
      this.tl6.to(".elements", 0, {autoAlpha:1});
      this.tl6.to(".smart-citizen .elements, .smart-green .elements, .smart-mobility .elements, .smart-water .elements, .smart-safety .elements", 0, {autoAlpha:0});
  $(this).click(function(){
    if( $(this).hasClass('active') ){
      $(this).removeClass('active');
      this.tl6.reverse();
    }else{
      $('.interactivo .default-container .menu ul li a').removeClass('active');
      $(this).addClass('active');
      this.tl6.play();
      }
  });
});

$('.interactivo .default-container .menu ul li a.menu-safety').each( function(){
      this.tl7 = new TimelineMax({paused:true});
      this.tl7.to(".elements", 0, {autoAlpha:1});
      this.tl7.to(".smart-citizen .elements, .smart-green .elements, .smart-mobility .elements, .smart-water .elements, .smart-efficiency .elements", 0, {autoAlpha:0});
  $(this).click(function(){
    if( $(this).hasClass('active') ){
      $(this).removeClass('active');
      this.tl7.reverse();
    }else{
      $('.interactivo .default-container .menu ul li a').removeClass('active');
      $(this).addClass('active');
      this.tl7.play();
      }
  });
});

 

So as you can see for each element what I do is onclick:

- Show all the elements of the map (so if you left any other activated menu item it doesn't matter) 

- Hide all the elements except the ones of the clicked item.

- Add active class to the menu item.

 

When I am doing it on each element individually (active / deactivate) is working perfectly infinitely. Also if I click on Element 1, then Element 2, then Element 3 etc is also showing and hiding my elements perfectly but only the first time. My problem is that  when I want to repeat this action, so click on each element again (1, 2, 3...3,2,1) then the action of show all the elements again and then hide is not working. Is just working the addClass/removeClass.

 

In my demo now I only have 1 item for Element 2 and one item for Element 3. The others have to hide/show everything.
https://codepen.io/MZBS/project/editor/XEkLMr

 

Any idea what I am doing wrong?

 

Thanks!!

 

 

Share this post


Link to post
Share on other sites

Hey MZBS, You're got a lot going on here :) 

 

In general, if you notice that you're repeating a lot of code but just changing the variable names (i.e. tl1, tl2, etc.) then you should usually try to refractor your code to keep it DRY (Don't Repeat Yourself). That means that you should usually abstract whatever you are repeating so that you don't have to repeat yourself so much. 

 

With that being said, I think the main issue is that you have a bunch of timelines that are conflicting because they are trying to set the same properties on the same elements. So it is easy to loose track (logic wise) of what is affecting stuff. I think that making your code more abstract will actually help you fix this issue!

 

For example, you could refractor the code above to work more generically and with more tweens and less timelines (to avoid conflicts) by doing something like this:

 

function hideAllElse(container) {
  // Immediately hide the contents
  TweenMax.set($('.interactivo .elements'), {autoAlpha: 0});
  // Fade in the given one
  if(container) {
  	TweenMax.to(container.querySelector(".elements"), 1, {autoAlpha: 1});
  }
}

$('.interactivo .default-container .menu ul li a').each( function(){
  $(this).click(function(){
    if( $(this).hasClass('active') ){
      $(this).removeClass('active');
      hideAllElse();
    } else {
      $('.interactivo .active').removeClass('active');
      $(this).addClass('active');
      hideAllElse(this);
    }
  });
});

Note that this is untested and probably uses the wrong selectors (your markup is not entirely clear to me plus there seems to be a lot of unnecessary elements to show the issue) so it won't work but hopefully this shows the basic approach. 

  • Like 2

Share this post


Link to post
Share on other sites

Hello Zack,

I know is a lot of code but each element has its own options and that's why I was creating this like that.

Your example is perfect if I want to hide / show all the elements on the map but that's not the goal.

 

So to understand better what I have, here is a little explanation:

- I have 6 types of categories of the elements in my map that by default all are shown on the map.

- My menu works like a filter so you can only hide / show the elements of the category you clicked. This is working perfectly now. 

- And if I click first to a category and then to a different category what I need is to display only the elements of that new category that is working fine also but only the first time.

 

So at the end for each category I need special indications: hide all the elements, show only the elements of the category. Then if I click to a different category would be the same, hide all the elements and show only of the category I clicked. And if I click to the same button then I see all the elements of all the categories in the map. 

 

So the animation is the same but the classes are different for each element. 

 

Share this post


Link to post
Share on other sites
11 minutes ago, MZBS said:

So the animation is the same but the classes are different for each element. 

I'd recommend using an approach similar to the one in my last post but using classes to indicate which ones should be hidden/shown. 

 

Overall this isn't really a question about GSAP, it's just getting your logic correct :) Unfortunately we don't have the time to sort it all out for you, but I really do think that you'd have an easier time if you abstracted it a bit more.

Share this post


Link to post
Share on other sites

Thank you Zack,

 

I was working with a new version with a different way to do this (by adding or removing classes to hide and show) and not that related with GSAP (without using timelines) and now is working perfectly. I know is still "too much code" for a menu and I would try to find how to make this cleaner but have to find the way to related each menu element with their own elements on the map. Here the code that is working fine:

 

$('.interactivo .default-container .menu ul li a.menu-citizen').each( function(){
  $(this).click(function(){
    if( $(this).hasClass('active') ){
        $(this).removeClass('active');
        $('.smart-citizen .elements').removeClass('on');
        $('.elements').removeClass('off');
        $('.elements').addClass('on');
      }else{
        $('.interactivo .default-container .menu ul li a').removeClass('active'); 
        $(this).addClass('active');
        $('.elements').removeClass('on');
        $('.elements').addClass('off');
        $('.smart-citizen .elements').removeClass('off');
        $('.smart-citizen .elements').addClass('on');
      }
  });
});

$('.interactivo .default-container .menu ul li a.menu-water').each( function(){
  $(this).click(function(){
    if( $(this).hasClass('active') ){
        $(this).removeClass('active');
        $('.smart-water .elements').removeClass('on');
        $('.elements').removeClass('off');
        $('.elements').addClass('on');
    }else{
      $('.interactivo .default-container .menu ul li a').removeClass('active');
        $(this).addClass('active');
        $('.elements').removeClass('on');
        $('.elements').addClass('off');
        $('.smart-water .elements').removeClass('off');
        $('.smart-water .elements').addClass('on');
      }
  });
});

$('.interactivo .default-container .menu ul li a.menu-mobility').each( function(){
  $(this).click(function(){
    if( $(this).hasClass('active') ){
        $(this).removeClass('active');
        $('.smart-mobilty .elements').removeClass('on');
        $('.elements').removeClass('off');
        $('.elements').addClass('on');
    }else{
      $('.interactivo .default-container .menu ul li a').removeClass('active');
        $(this).addClass('active');
        $('.elements').removeClass('on');
        $('.elements').addClass('off');
        $('.smart-mobility .elements').removeClass('off');
        $('.smart-mobility .elements').addClass('on');
      }
  });
});

$('.interactivo .default-container .menu ul li a.menu-green').each( function(){
  $(this).click(function(){
    if( $(this).hasClass('active') ){
        $(this).removeClass('active');
        $('.smart-green .elements').removeClass('on');
        $('.elements').removeClass('off');
        $('.elements').addClass('on');
    }else{
      $('.interactivo .default-container .menu ul li a').removeClass('active');
        $(this).addClass('active');
        $('.elements').removeClass('on');
        $('.elements').addClass('off');
        $('.smart-green .elements').removeClass('off');
        $('.smart-green .elements').addClass('on');
      }
  });
});

$('.interactivo .default-container .menu ul li a.menu-efficiency').each( function(){
  $(this).click(function(){
    if( $(this).hasClass('active') ){
        $(this).removeClass('active');
        $('.smart-efficiency .elements').removeClass('on');
        $('.elements').removeClass('off');
        $('.elements').addClass('on');
    }else{
      $('.interactivo .default-container .menu ul li a').removeClass('active');
        $(this).addClass('active');
        $('.elements').removeClass('on');
        $('.elements').addClass('off');
        $('.smart-efficiency .elements').removeClass('off');
        $('.smart-efficiency .elements').addClass('on');
      }
  });
});

$('.interactivo .default-container .menu ul li a.menu-safety').each( function(){
  $(this).click(function(){
    if( $(this).hasClass('active') ){
        $(this).removeClass('active');
        $('.smart-safety .elements').removeClass('on');
        $('.elements').removeClass('off');
        $('.elements').addClass('on');
    }else{
      $('.interactivo .default-container .menu ul li a').removeClass('active');
        $(this).addClass('active');
        $('.elements').removeClass('on');
        $('.elements').addClass('off');
        $('.smart-safety .elements').removeClass('off');
        $('.smart-safety .elements').addClass('on');
      }
  });
});

 

But you are right this is not related anymore with GSAP with this way to do it so thank you anyways for your time!

 

Thanks.

MZ.

 

Share this post


Link to post
Share on other sites

This thread might help you out.

 

 

  • Like 3
  • Thanks 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.

×