'How to animate a svg path such that another different colored path slowly starts filling it?

I have an SVG that kind of looks like a race track encoded in the form of a <path> element. What i want is to animate another path with a different color which starts from one end of the race track and fills to the other end (animation).

Here's the SVG for the race track thing :

<svg viewBox="0 0 1307 772" fill="none" xmlns="http://www.w3.org/2000/svg">
   <path d="M305 19C385.381 71.1047 436 74 538.5 81.5C641 89 716.5 104 755.5 103C794.5 102 1029 81.5 1029 81.5C1052.73 83.3972 1068.89 91.3809 1102.5 117.5C1121.72 137.652 1127.34 151.094 1131.5 177.5C1130.72 202.494 1140.5 224 1129.5 241.5C1118.5 259 1064.62 273.928 1029 274L931.5 298H855.5H798.5L666 317H487L384 298H272.5L74.5 341.5L42 379.5L35 387.685L23.5 416.5L35 447L74.5 469L229 488L451.5 515H487H704L788 526L988.5 542.5L1156.5 558.5L1235 599C1295.85 629.595 1299.04 647.455 1254 680.5L1129.5 745.5" stroke="#403737" stroke-width="36" stroke-linecap="round"/>
</svg>

The race track would have some kind of checkpoints to it and from javascript i want to animate the filler color to reach only that checkpoint.

How can I achieve this ? Thank you for your help :)



Solution 1:[1]

Give the power to HTML, create your own standard JavaScript Web Component <svg-track>

<svg-track length="50">
  <path stroke="green" stroke-width="30"
        d="M20 20H200"/>
</svg-track>

<svg-track dur="2" length="70" viewBox="0 0 400 100">
  <path stroke="blue" stroke-width="36" stroke-linecap="round"
        d="M20 30l40 30l40 -30l40 30h200"/>
</svg-track>

<svg-track dur="3" length="100" viewBox="0 0 800 60">
  <path stroke="red" stroke-width="60" stroke-linecap="round"
        d="M800 30h-800"/>
</svg-track>

<script>
customElements.define("svg-track", class extends HTMLElement {
  connectedCallback() {
    setTimeout(() => { // make sure innerHTML is parsed
      let attr = name => this.getAttribute(name);
      this.innerHTML = `<svg style="background:lightgrey;height:60px;max-width:100vw"
                             viewBox="${attr("viewBox")||"0 0 200 40"}" fill="none">
                          ${this.innerHTML}</svg>`;
      let path = this.querySelector("path");
      path.setAttribute("pathLength", 100);
      path.setAttribute("stroke-dasharray", 100);
      path.innerHTML =`<animate dur="${attr("dur")||1}s" to="${100-attr("length")}"
                        attributeName="stroke-dashoffset" from="100" fill="freeze" 
                        repeatCount="1" begin="0s"/>`;  
    })
  }
})
</script>

svga

Solution 2:[2]

Here I copied the path, set a pathLength on the path and animate the stroke-dasharray from 0 100 to 100 100.

#p1 {
  stroke-dasharray: 0 100;
  animation: stroke 5s linear forwards;
}

@keyframes stroke {
  100% {
    stroke-dasharray: 100 100;
  }
}
<svg viewBox="0 0 1307 772" fill="none" xmlns="http://www.w3.org/2000/svg">
   <path d="M305 19C385.381 71.1047 436 74 538.5 81.5C641 89 716.5 104 755.5 103C794.5 102 1029 81.5 1029 81.5C1052.73 83.3972 1068.89 91.3809 1102.5 117.5C1121.72 137.652 1127.34 151.094 1131.5 177.5C1130.72 202.494 1140.5 224 1129.5 241.5C1118.5 259 1064.62 273.928 1029 274L931.5 298H855.5H798.5L666 317H487L384 298H272.5L74.5 341.5L42 379.5L35 387.685L23.5 416.5L35 447L74.5 469L229 488L451.5 515H487H704L788 526L988.5 542.5L1156.5 558.5L1235 599C1295.85 629.595 1299.04 647.455 1254 680.5L1129.5 745.5" stroke="#403737" stroke-width="36" stroke-linecap="round"/>
   <path id="p1" d="M305 19C385.381 71.1047 436 74 538.5 81.5C641 89 716.5 104 755.5 103C794.5 102 1029 81.5 1029 81.5C1052.73 83.3972 1068.89 91.3809 1102.5 117.5C1121.72 137.652 1127.34 151.094 1131.5 177.5C1130.72 202.494 1140.5 224 1129.5 241.5C1118.5 259 1064.62 273.928 1029 274L931.5 298H855.5H798.5L666 317H487L384 298H272.5L74.5 341.5L42 379.5L35 387.685L23.5 416.5L35 447L74.5 469L229 488L451.5 515H487H704L788 526L988.5 542.5L1156.5 558.5L1235 599C1295.85 629.595 1299.04 647.455 1254 680.5L1129.5 745.5" pathLength="100"  stroke="red" stroke-width="14" stroke-linecap="round" />
</svg>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 chrwahl