john_snow5214
john_snow5214

Reputation: 192

How to animate svg path filling in javascript instead of HTML

I am wanting to know how could I animate SVG path with javascript instead of HTML. At the moment, I have found several overflow articles regarding the animation with javascript and have found many in jQuery with changing the attributes in javascript.

The links I found: Fill color SVG path with animation Animate SVG path via javascript

Does anyone might know how could I apply the techniques to the path below, as it works fine with HTML, but I would like to control the duration of the animation.

			<svg width="300" height="300">
        <defs>
    <linearGradient id="left-to-right">
      <stop offset="0" stop-color="#ff0000">
        <animate dur="2s" attributeName="offset" opacity= 0.1 fill="freeze" from="0" to="1" />
      </stop>
      <stop offset="0" stop-color="#fff" stop-opacity= "0.1">
        <animate dur="2s" attributeName="offset" opacity= 0.1 fill="freeze" from="0" to="1" />
      </stop>
    </linearGradient>
  </defs>
         <path id="myPath"
					d="M 280 210 Q 237 144 180 140 Q 120 144 80 210 L 280 210 "
					stroke="black" fill="url(#left-to-right)" />
      </svg>
      

The thing is that the javascript is just not working

$(function(){
  
    $(this).animate(
      {
        textIndent: 1,
      }, {
        duration: 3000,
	step: function ( now, fx ) {
                var from = 0,
                	  to = 700,
                    r = from + to * ( now - fx.start ) / ( fx.end - fx.start );
                
                $("#left-to-right").attr( "from", 0);
                $("#left-to-right").attr( "from", 1);
			  },
        complete: function () {
          $("#myPath").attr("fill", "url(#left-to-right)");
        }
      }
    );
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg width="300" height="300">
        <defs>
    <linearGradient id="left-to-right">
      <stop offset="0" stop-color="#ff0000">
        <animate dur="2s" attributeName="offset" opacity= 0.1 fill="freeze" from="0" to="1" />
      </stop>
    </linearGradient>
  </defs>
         <path id="myPath"
					d="M 280 210 Q 237 144 180 140 Q 120 144 80 210 L 280 210 "
					stroke="black" fill="url(#left-to-right)" />
      </svg>

How do I have to change the javascript now, fx and attributes, to make the animation work as it does with current HTML?

Upvotes: 3

Views: 1204

Answers (1)

enxaneta
enxaneta

Reputation: 33062

If you want to use javascript to animate the gradient you don't need the <animate> element any longer.

//all the stops
let ss = document.querySelectorAll("#left-to-right stop");
let start = null;
let progress = 0;//the progress of the animation
let duration = 2000; //2 seconds in millisecinds
let rid = null;//request animation id

function Frame(timestamp) {
  rid = window.requestAnimationFrame(Frame);

  if (!start) start = timestamp;
  progress = timestamp - start;
  
  if (progress <= duration) {
   //for each stop reset the offset attribute
    ss.forEach(s => {
      s.setAttributeNS(null, "offset", progress / duration);
    });
  }
  // if the animation is over cancel the animation
  if (progress >= duration){window.cancelAnimationFrame(rid)}
}

Frame();
<svg width="300" height="300">
    <defs>
    <linearGradient id="left-to-right">
      <stop offset="0" stop-color="#ff0000"></stop>
      <stop offset="0" stop-color="#fff" ></stop>
    </linearGradient>
  </defs>
  <path id="myPath" d="M 280 210 Q 237 144 180 140 Q 120 144 80 210 L 280 210" stroke="black" fill="url(#left-to-right)" />
</svg>

I hope you'll find this useful.

Upvotes: 5

Related Questions