Jump to content
GreenSock

neumonic

Multiple SVG Line animations in different sections on horizontal scroll

Recommended Posts

Hi there! I am attempting to animate multiple line dash svgs in multiple sections of a horizontal scroll container, but I am only successful with doing this on the first one. Similarly, what is the most performant way to do this in the view dynamically? My initial thought is to store the SVGS in an array and loop through the array to render them in the template, but perhaps there is an easier way to do this with GSAP. I would also assume that I could keep the same type of drawing in animation but would need to tweak the starting and ending position in each section. Maybe the better way to do this is trigger via an element verses the container? Any help would be greatly appreciate. Thank you!

See the Pen JjOOPNe by jshuadvd (@jshuadvd) on CodePen

Link to comment
Share on other sites

Welcome to the forums, @neumonic

 

I noticed several issues: 

  1. Your first path is an actual line that has a legitimate dashed stroke applied, but your second path isn't a line at all - it literally appears to have the "dashes" baked into the artwork itself (not a dashed stroke...literally a path with a bunch of chunks taken out of it).. So the stroke won't behave the way you're expecting. You need to fix your SVG artwork.
  2. You're creating your ScrollTriggers out of order. You should always create them in the order they appear on the screen -or- set the refreshPriority values accordingly.
  3. It looks like you were expecting some of the scrollTriggers to have their start/end based horizontally, but you forgot to give them a containerAnimation value. So they were just acting like normal vertical ScrollTriggers.
  4. You used drawSVG on some of the strokes, but a CSS variable --dashOffset on others...and you seemingly tried to set that initially in an attribute instead of CSS style. I would definitely recommend sticking with drawSVG, and don't use CSS variables in an attribute.

My advice would be to ignore the scrolling part completely for now - just get the animation to run on its own first the way you want it. THEN once that's beautiful, hook it up to a ScrollTrigger.

 

Good luck!

  • Like 3
Link to comment
Share on other sites

Hi @GreenSock :) Thank you for the kind welcome as well as the quick response. 

1. I have removed the second SVG. I realize that the artwork is flawed there. I am now using another SVG that isn't. 
2. I have updated the order as well. 
3. I have updated the `containerAnimation` value and it seems that the triggers are now working horizontally. 
4. Yes, I was following what Cassie did here: 

 where they used both DrawSVG for the mask as well as the css variable for the actual stroke. 

Thank you for your advice. I was able to update the first two sections and they are now working properly. 

See the Pen JjOOPNe?editors=1000 by jshuadvd (@jshuadvd) on CodePen



My next question is, what would be the best way to do this dynamically from a GSAP perspective? I have 7 or 8 of these sections with different SVG's in each. It would be ideal to attempt to maintain DRY philosophy, if at all possible... My initial thought is to store the sections and SVGS in an array loop through and create a .from for each mask and stroke and then update the trigger class from there as well. 

Thanks again :)

Link to comment
Share on other sites

Yep, I'd just add a common class to each of your important elements (like all the <mask> elements have a class of "stroke-mask", the masked <path> has a class of "mask-stroke", etc.) and do a simple .forEach() loop inside of which you can use .querySelector() to grab the one that's in that particular module, sorta like: 

gsap.utils.toArray(".module").forEach(module => {
  let strokeMask = module.querySelector(".stroke-mask"),
      maskStroke = module.querySelector(".mask-stroke"),
      stroke = module.querySelector(".stroke");
  if (strokeMask) {
    gsap.from(maskStroke, {
      drawSVG: "0%",
      scrollTrigger: {
        trigger: module,
        start: "left left",
        end: "right left",
        scrub: 1,
        containerAnimation: scrollTween,
      }
    });
    gsap.from(stroke, {
      "--dashOffset": 1000,
      scrollTrigger: {
        trigger: module,
        start: "left left",
        end: "right left",
        scrub: 1,
        containerAnimation: scrollTween,
      }
    });
  }
});

If each one needs a slightly different start/end or whatever, you can just use a data- attribute on the element(s) and access that in your loop accordingly.

 

Good luck!

  • Like 2
Link to comment
Share on other sites

Thank you again for the awesome help @GreenSock I truly appreciate it!

I have updated my code to reflect your feedback. 

See the Pen JjOOPNe by jshuadvd (@jshuadvd) on CodePen


Almost everything is good to go with one exception. The actual drawing in of the path. The dash array does animate just fine... I think this is because (please correct me if I am wrong) you can only target the mask via an id? So, mask="url(.stroke-mask)" would not work? If that is the case, I am not 100% certain how do that dynamically.  Any insight is greatly appreciated :) Thanks again!



 

Link to comment
Share on other sites

3 hours ago, neumonic said:

you can only target the mask via an id? So, mask="url(.stroke-mask)" would not work? If that is the case, I am not 100% certain how do that dynamically.

I believe that's true, so you can simply add an id to each one accordingly. You don't need to use a class for that part. Something can have an id and a class. See what I mean? 

  • Like 1
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.
×