2

I have use following way to fill color of SVG paths. Is there a way to add animation to it. Color filling starting from center and spread.

$(function(){
    $("#btn-test1").on("click",function(){
        $("#path1").attr("fill","#0000");   

    });
});
isuru
  • 3,385
  • 4
  • 27
  • 62

1 Answers1

6

This answer provides four different options to animate the fill color of a SVG path using jQuery.animate(), CSS @keyframes and SVG SMIL-Animation:

#1 jQuery.animate() and SVG <radialGradient>

$(function(){
  $("button").on("click",function(){
  
    $(this).animate(
      {
        textIndent: 1, // or whatever
      }, {
        duration: 3000,
 step: function ( now, fx ) {
             // arguments:
                // now: numeric value of the property being animated at each step
                // fx: reference to the jQuery.fx prototype object
                 // fx.start: first value of the animated property
                    // fx.end: last value of the animated property
                var from = 0,
                   to = 700,
                    r = from + to * ( now - fx.start ) / ( fx.end - fx.start ); // animate r from 0 to 700
                
                $("#gradient").attr( "r", r + "px" );
     },
        complete: function () {
          $("#path").attr("fill", "#000"); // callback
        }
      }
    );
    
  });
});
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<head>
<body>

  <button>Start Animation</button>
  
  <svg height="150" width="300">
    <defs>
      <radialGradient id="gradient" r="0px" gradientUnits="userSpaceOnUse">
        <stop offset="20%" style="stop-color: #000; stop-opacity: 1" />
        <stop offset="100%" style="stop-color: #000; stop-opacity: 0" />
      </radialGradient>
    </defs>
    <path id="path" d="M 0 0 Q 300 300 300 0 z" fill="url(#gradient)" />
  </svg>
</body>



#2 jQuery.animate() and SVG transform attribute

$(function(){
  $("button").on("click",function(){
  
    $(this).animate(
      {
        textIndent: 1, // or whatever
      }, {
        duration: 3000,
 step: function ( now, fx ) {
             // arguments:
                // now: numeric value of the property being animated at each step
                // fx: reference to the jQuery.fx prototype object
                 // fx.start: first value of the animated property
                    // fx.end: last value of the animated property
                var from = 0,
                   to = 1,
                    scale = from + to * ( now - fx.start ) / ( fx.end - fx.start ); // animate r from 0 to 700
                
                $("#path").attr( "transform", "scale(" + scale + ")" );
     }
      }
    );
    
  });
});
#path {transform-origin: 50% 50%;}
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>

  <button>Start Animation</button>
  
  <svg height="150" width="300">
     <path id="path" d="M 0 0 Q 300 300 300 0 z" fill="#000" />
  </svg>

</body>

Maybe that isn’t the result you expected, but it’s an option.



#3 CSS @keyframes

stop {
  stop-opacity: 0;
  animation: 3s animateStopOpacity;
}
stop:last-child {
  animation-delay: 2s;
}

@keyframes animateStopOpacity {
    from {stop-opacity: 0;}
    to {stop-opacity: 1;}
}
<body>
  <svg height="150" width="300">
    <defs>
      <radialGradient id="gradient" r="50%" gradientUnits="userSpaceOnUse">
        <stop offset="0%" style="stop-color: #000; stop-opacity: 1" />
        <stop offset="100%" style="stop-color: #000; stop-opacity: 0" />
      </radialGradient>
    </defs>
    <path id="path" d="M 0 0 Q 300 300 300 0 z" fill="url(#gradient)" />
  </svg>
</body>



#4 SVG SMIL Animation

<body>

  <svg height="150" width="300">
    <defs>
      <radialGradient id="gradient" r="100px" gradientUnits="userSpaceOnUse">
        <stop offset="20%" style="stop-color: #000; stop-opacity: 1" />
        <stop offset="100%" style="stop-color: #000; stop-opacity: 0" />
        <animate 
     attributeName="r"
     from="0"
     to="700"
     dur="3s"
     fill="freeze" 
       />
      </radialGradient>
    </defs>
    <path id="path" d="M 0 0 Q 300 300 300 0 z" fill="url(#gradient)" />
  </svg>

</body>



I hope I could help you!

jak.b
  • 273
  • 4
  • 15
  • Really good explanation and let me know is there a way to fill SVG as gradients in a dynamic way without defining radial-gradient within SVG? – isuru Jan 06 '18 at 09:12
  • 1
    @isuru Yes, certainly. But SVG is a XML-based markup language, so you cannot do that with jQuery. If you could use another library, use [snap.svg](http://snapsvg.io/) or [svg.js](http://svgjs.com/). Otherwise you have to use document.createElementNS("www.w3.org/2000/svg", "radialGradient"). See [this](https://stackoverflow.com/questions/3642035/jquerys-append-not-working-with-svg-element) question to learn more. – jak.b Jan 07 '18 at 20:24