I have this SVG
<svg width="455" height="102" viewBox="0 0 455 102" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M451.556 25.1576C435.152 73.3258 366.885 125.586 296.309 84.449C257.221 59.9286 203.507 18.9945 182.449 13.1117C114.633 -12.4168 41.0939 12.8604 2.57437 66.1813" stroke="white" stroke-width="5" stroke-miterlimit="10" stroke-linecap="round" stroke-dasharray="10 20 10 20 10 20"/>
<path d="M451.556 25.1576C435.152 73.3258 366.885 125.586 296.309 84.449C257.221 59.9286 203.507 18.9945 182.449 13.1117C114.633 -12.4168 41.0939 12.8604 2.57437 66.1813" stroke="#222222" stroke-opacity="0.3" stroke-width="5" stroke-miterlimit="10" stroke-linecap="round" stroke-dasharray="10 20 10 20 10 20"/>
</svg>
My goal is to animate each square a blue color based on some application state , the idea is that it is a loader and it finishes all blue once the data has came in. So the end result will look like this
<svg width="455" height="102" viewBox="0 0 455 102" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M451.556 25.1576C435.152 73.3258 366.885 125.586 296.309 84.449C257.221 59.9286 203.507 18.9945 182.449 13.1117C114.633 -12.4168 41.0939 12.8604 2.57437 66.1813" stroke="#007CFF" stroke-width="5" stroke-miterlimit="10" stroke-linecap="round" stroke-dasharray="10 20 10 20 10 20"/>
</svg>
Appreciate any tips and how to go about doing this
CodePudding user response:
Use an SVG mask animation.
The bottom layer is a blue curve
Top layer - gray curve
When the mask is animated from left to right, the upper gray curve is cut through and the lower blue curve becomes visible as a result.
<animate attributename="x" begin="svg1.click" dur="4s" values="-452;0" repeatCount="indefinite" />
An illusion is created of filling the curve gray color with a blue.
Animation will start after clicking
<svg id="svg1" width="455" height="102" viewBox="0 0 455 102" fill="none" xmlns="http://www.w3.org/2000/svg">
<defs>
<mask id="msk">
<rect width="100%" height="100%" fill="white" />
<rect fill="black" x="-452" y="0" width="450" height="100" >
<animate id="an" attributeName="x" begin="svg1.click;an.end 0.5s" dur="7s" values="-452;10" repeatCount="1" fill="freeze" />
</rect>
</mask>
</defs>
<path id="path" d="M451.556 25.1576C435.152 73.3258 366.885 125.586 296.309 84.449C257.221 59.9286 203.507 18.9945 182.449 13.1117C114.633 -12.4168 41.0939 12.8604 2.57437 66.1813" stroke="#007CFF" stroke-width="5" stroke-miterlimit="10" stroke-linecap="round" stroke-dasharray="10 20"/>
<path mask="url(#msk)" d="M451.556 25.1576C435.152 73.3258 366.885 125.586 296.309 84.449C257.221 59.9286 203.507 18.9945 182.449 13.1117C114.633 -12.4168 41.0939 12.8604 2.57437 66.1813" stroke="#BCBCBC" stroke-width="5" stroke-miterlimit="10" stroke-linecap="round" stroke-dasharray="10 20"/>
</svg>
Update
as commented @Dmitriy
For Example- the data comes in in 4 seconds instead of 7 seconds - could i instantly finish the animation once that happens?
For this you can use repeatDur This attribute stops the animation from playing after a certain amount of time from the start of the animation! Simply put, repeatDur limits the duration of an animation.
<svg id="svg1" width="455" height="102" viewBox="0 0 455 102" fill="none" xmlns="http://www.w3.org/2000/svg" style="border:1px solid">
<defs>
<mask id="msk">
<rect width="100%" height="100%" fill="white" />
<rect fill="black" x="-452" y="0" width="450" height="100" >
<animate id="an" attributeName="x" begin="svg1.click" dur="7s" repeatDur="4s" values="-452;10" repeatCount="1" fill="freeze" />
</rect>
</mask>
</defs>
<path id="path" d="M451.556 25.1576C435.152 73.3258 366.885 125.586 296.309 84.449C257.221 59.9286 203.507 18.9945 182.449 13.1117C114.633 -12.4168 41.0939 12.8604 2.57437 66.1813" stroke="#007CFF" stroke-width="5" stroke-miterlimit="10" stroke-linecap="round" stroke-dasharray="10 20"/>
<path mask="url(#msk)" d="M451.556 25.1576C435.152 73.3258 366.885 125.586 296.309 84.449C257.221 59.9286 203.507 18.9945 182.449 13.1117C114.633 -12.4168 41.0939 12.8604 2.57437 66.1813" stroke="#BCBCBC" stroke-width="5" stroke-miterlimit="10" stroke-linecap="round" stroke-dasharray="10 20"/>
</svg>