Jump to content
Search Community

Animation only working once with multiple elements and timelines

MZBS 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

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!!

 

 

See the Pen XEkLMr by MZBS (@MZBS) on CodePen

Link to comment
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
Link to comment
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. 

 

Link to comment
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.

Link to comment
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.

 

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...