svggsapsmilscrolltrigger

Animate SVG on scroll using GSAP


GSAP has this ScrollTrigger plugin that will trigger animations on scroll, that I would like to use.

I already got a working SVG animation (without GSAP):

<svg width="596" height="255">
  
  <linearGradient id="prog-mask" x1=0% x2="100%" y1="0%" y2="100%">
      <stop offset="0%"  stop-color="white" stop-opacity="1" />
      <stop offset="5%"  stop-color="white" stop-opacity="0">
      <animate attributeName="offset" values="0; 1" dur="2s" begin="0s" repeatCount="0" fill="freeze" />
      <animate attributeName="stop-opacity" values="0; 1" dur="2s" begin="2s" repeatCount="0" fill="freeze" />
    </stop>
 <stop offset="100%"  stop-color="white" stop-opacity="0" />
  </linearGradient>
  
  
  <mask id="prog-render">
  <rect x="0" y="0" width="100%" height="100%" fill="url(#prog-mask)"/>     
  </mask>
  
  <pattern id="pattern-circles" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
    <circle cx="6" cy="6" r="3" stroke="red" stroke-width="2" fill="transparent">

      <animate attributeName="r" values="0; 5" dur="2s" begin="0s" repeatCount="0" fill="freeze" />
    </circle>

  </pattern>
  <!-- The canvas with our applied pattern -->
  <rect x="0" y="0" width="100%" height="100%" fill="url(#pattern-circles)" mask="url(#prog-render)"/>
</svg>

As mentioned, this SVG animation is not hooked up with GSAP (which I believe is a must if it should work in conjunction with the ScrollTrigger plugin?)

That's why I have tried to create this animation using GSAP:

// 1. offset
gsap.to("#prog-mask stop:nth-child(2)", {
  duration: 2,
  attr: { offset: 1, fill: "freeze" },
  repeat: 1,
  delay: 0
});

// 2. stop-opacity
gsap.to("#prog-mask stop:nth-child(2)", {
  duration: 5,
  attr: { stopOpacity: 1, fill: "freeze" },
  repeat: 1,
  delay: 2
});

// 3. r = radius
gsap.to("circle", {
  duration: 5,
  attr: { r: 5, fill: "transparent" },
  repeat: 0,
  delay: 0
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.6.0/gsap.min.js"></script>

<section>
<svg width="596" height="255">
  
  <linearGradient id="prog-mask" x1=0% x2="100%" y1="0%" y2="100%">
    
      <stop offset="0%" stop-color="white" stop-opacity="1" />
    
      <stop offset="5%"  stop-color="white" stop-opacity="0">
        
    <!-- <animate attributeName="offset" values="0; 1" dur="2s" begin="0s" repeatCount="0" fill="freeze" />
        
      <animate attributeName="stop-opacity" values="0; 1" dur="2s" begin="2s" repeatCount="0" fill="freeze" />-->
        
    </stop>
    
 <stop offset="100%"  stop-color="white" stop-opacity="0" />
  </linearGradient>
  
  
  <mask id="prog-render">
  <rect x="0" y="0" width="100%" height="100%" fill="url(#prog-mask)"/>     
  </mask>
  
  <pattern id="pattern-circles" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
    
    <circle cx="6" cy="6" r="0" stroke="red" stroke-width="1.5" fill="transparent">

      <!--<animate attributeName="r" values="0; 5" dur="2s" begin="0s" repeatCount="0" fill="freeze" />-->
      
    </circle>

  </pattern>
  <!-- The canvas with our applied pattern -->
  <rect id="rect" x="0" y="0" width="100%" height="100%" fill="url(#pattern-circles)" mask="url(#prog-render)"/>
</svg>
</section>

As you can tell, I have basically just tried to replace the three <animate> elements with some GSAP code.

At this point the dots are revealed immediately and not revealed in a linear fashion from top left to bottom right.

Also, for some unknown reason, the whole rectangle is gradient (actually, I don't mind this effect, but I don't understand why it is happening?).

  1. Do I have to animate this SVG in GSAP to use ScrollTrigger?
  2. How can I get the original animation result using GSAP?
  3. Why does this color gradient happen in the GSAP code?

Solution

  • Do I have to animate this SVG in GSAP to use ScrollTrigger?

    It depends. If you just want to fire off an animation (SMIL animation, CSS animation, GSAP animation, whatever), you could use the ScrollTrigger callbacks to do that.

    If you want to scrub through the animation it probably makes sense to make the animation in GSAP because it's easier to update. AFAIK, you can't tell SMIL animations to go to a specific progress point like you can with GSAP.

    With that being said, pretty much everyone who animates SVGs regularly recommends using JS for your SVG animations in most cases (more info on that here).

    Why does this color gradient happen in the GSAP code?

    If you look at the SVG of the GSAP version with your dev tools you can see it's animating a stopOpacity attribute instead of the stop-opacity attribute. Using the regular attribute name (i.e. not camel-case) inside of quotes fixes that.

    How can I get the original animation result using GSAP?

    I'd make use of GSAP's timeline functionality to set things up like this: Demo.