Jump to content
Search Community

Simultaneous timelines animating Linear Gradient offset with different repeat values

Chromium test
Moderator Tag

Go to solution Solved by OSUblake,

Recommended Posts

So I'm trying to animate the fill for multiple SVGs (the same SVG shown multiple times on the page) using Linear Gradients and animating the offset for said gradients using GSAP. While I have successfully done that for one and multiple SVGs at a time, I seem to be hitting 2 different problems that I'm struggling to wrap my head around.

 

I have the following scenario, imagine putting the same SVG that requires the same animation mentioned above multiple times on the page. I've wrapped each of my SVGs with a simple div that I then target via a jQuery.each for loop and create a new timeline for each SVG (wrapper div). I've hit the following roadblocks:

  1. All goes well if all the SVGs have the same repeat value. As soon as I customize this repeat value to something different for any one of the SVGs, all hell breaks lose. This is demonstrated in my CodePen above. When circle #2 is set to a repeat of "2"... it seems to stop when it's supposed to but it also doesn't...? I really can't even explain what's happening here. It seems like this is simple enough that it shouldn't cause a problem but then again, #2 below is quite a big problem that may or may not be relevant to this one.
  2. This one in particular I'm not certain is involved in problem #1 above, but if it is, then it would certainly explain the erratic behavior seen in the CodePen. It seems that one of the greatest (and worst) things about SVGs is linear gradients. Since I've got the same SVG multiple times on the same page, perks of that is that they all share the same linearGradient IDs... based on my research that would cause erratic behavior as the IDs are meant to be unique not just per SVG but per the whole DOM. Shocker! I don't know why we're limited to IDs then... but that's a rant for another day. Now before you say just change the IDs for each SVG, or even create a backend for loop that adds a unique token for each repeated ID, please have a look at the JS in my CodePen to see why that wouldn't make sense for my use case. Long story short, my JS animation code would also have to exponentiate in size and that would be impractical.

 

If my theory is correct, and the problem here is the linear gradient IDs not being unique, what can you guys say are my options? Are there any solutions to the linear gradient IDs that you guys know about that suit my use case? Or are there better ways to achieve my fill animation without linear gradients? I don't know why but I didn't seem to find any easier fill animation options for SVGs than this. Also keep in mind that my true SVG is far from a simple circle, so a solution like a moving <span> might be far from optimal in filling only a few objects inside of an SVG with many objects.

 

Apologies in advance for the headaches this may cause.

See the Pen abEYyzm by fuad-zeyad-tareq (@fuad-zeyad-tareq) on CodePen

Link to comment
Share on other sites

  • Solution

Welcome the to forums @Chromium

 

50 minutes ago, Chromium said:

If my theory is correct, and the problem here is the linear gradient IDs being not unique, what can you guys say are my options?

 

You are correct in thinking that IDs must unique. I also think you might be overthinking this problem a bit. Just set the IDs in your loop. You're practically doing the same thing with your fill attribute.

 

Sorry, I had a hard time reading that jQuery, so I did it all vanilla. I also added a little uniqueId function so you can get a unique ID from anywhere in your code.

 

See the Pen NWXYvmq by GreenSock (@GreenSock) on CodePen

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Quote

I also think you might be overthinking this problem a bit. Just set the IDs in your loop. You're practically doing the same thing with your fill attribute.

Ahahaha. Guilty as charged! Though to be fair, not being able to set the fill attribute to a linearGradient's class kinda made me assume that you can't put a class on linearGradients at all. This makes the world of difference!

 

I was even able to slightly improve the efficiency of the code (since in my case I had 8 unique gradients) with a for loop!!!

tl.from(...)
  .to(...);

  gradients.forEach(gradient => {
    t1.set(circle, { fill: `url(#${gradient.id})` })
      .to(gradient.querySelector("stop"), { attr: { offset: "100%" }});
  });
    
  t1.to(...)
    .to(...);
});

 

Thanks for the fast and efficient response Blake!
And awesome work with GSAP guys. Your scripts are some of the best I've seen in years!

  • Like 2
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...