How to Animate a Svg Figure Like a Progress Bar with CSS

How to animate a SVG figure like a progress bar with CSS

You can animate the gradient by animating the color-stop and/or the offset. Then by adjusting different values you may create the effect you want.

Here is a simple example where I animate the colors of the left one and the offset of the right one.

<div class="demo">  <svg class="progress"    xmlns="http://www.w3.org/2000/svg"    xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 209.29 106.77">    <defs>        <style>.cls-1{fill:url(#linear-gradient);}.cls-2{fill-rule:evenodd;fill:url(#linear-gradient-2);}</style>        <linearGradient id="linear-gradient" x1="208.06" y1="15.09" x2="148.49" y2="88.62" gradientUnits="userSpaceOnUse">            <stop offset="0" stop-color="#bababa"/>            <stop offset="0.28" stop-color="#979797">              <animate  attributeName="offset" values=".0;.28" dur="8s" fill="freeze"  />             </stop>            <stop offset="1" stop-color="#424242">                <animate attributeName="offset" values="0;1" dur="8s" fill="freeze"  />             </stop>            <stop offset="1" stop-color="rgba(0,0,0,0)">                <animate attributeName="offset" values="0;1" dur="8s" fill="freeze"  />             </stop>        </linearGradient>        <linearGradient id="linear-gradient-2" x1="12.55" y1="97.95" x2="78.02" y2="26.75" gradientUnits="userSpaceOnUse">            <stop offset="0" stop-color="rgba(0,0,0,0)">                            <animate attributeName="stop-color" values="rgba(0,0,0,0); #4682b4" dur="8s" fill="freeze"  />             </stop>            <stop offset="1" stop-color="rgba(0,0,0,0)">                  <animate attributeName="stop-color" values="rgba(0,0,0,0); #002e6e" dur="8s" fill="freeze"  />                </stop>          </linearGradient>    </defs>    <g id="c2" data-name="c2">        <g id="Layer_1" data-name="Layer 1">            <path class="cls-1" d="M135.21,71.21,130,76.3a52.67,52.67,0,0,0,9.56,8.58l1.43-1.76L208.64,0ZM160.15,89.3,158,93a52.93,52.93,0,0,0,14.44,1.23l.55-1.38L209.29,3.59Z"/>            <path class="cls-2" d="M24.42,9.83A52.69,52.69,0,0,0,8.24,82.57a51.86,51.86,0,0,0,3.65,5l5.16-5,.15-.15c-.68-.92-1.35-1.87-2-2.85a49.58,49.58,0,0,1,65.44-70A52.71,52.71,0,0,0,24.42,9.83Zm59,84.7a49.52,49.52,0,0,1-24.12,7.71l-1.61,4-.24.58A52.67,52.67,0,0,0,101.3,74.63,49.52,49.52,0,0,1,83.4,94.53Z"/>        </g>    </g>  </svg></div>

Slowly fill SVG image with color (like progress bar) using CSS

You can do this by animating a mask or a filter, and using the fakeSMIL library to polyfill for IE. Below is the filter version.

<svg width="800px" height="400px">  <defs>    <filter id="green-fill" x="0%" y="0%">      <feFlood flood-color="green"/>      <feOffset dy="210">        <animate attributeName="dy" from="300" to="210" dur="2s"/>        </feOffset>      <feComposite operator="in" in2="SourceGraphic"/>      <feComposite operator="over" in2="SourceGraphic"/>      </filter>    </defs>       <image filter="url(#green-fill)" xlink:href="https://cdn.mediacru.sh/P-WOGKdNDiGT.svg" height="400" width="700" />    </svg>

SVG progress bar with image

To solve, you need to combine two animations:

  1. Painting half of the arc from the beginning to the middle (top)
  2. Animation of movement of a circle with an image inside

Set the same time for both animations

<div class="w-100 case-progress-bar input p-2" style="position: relative;" data-percentage="80">
<svg class='progress_bar' viewBox="0 0 100 50" >

<g fill-opacity="0" stroke-width="4">
<path id="pfad" d="M5 50C5 44.1 6.1 38.5 8.2 33.4 10.8 26.8 14.9 20.9 20.2 16.3 28.1 9.3 38.6 5 50 5" stroke="#EBEDF8"></path>

<path d="M5 50a45 45 0 1 1 90 0" stroke="#EBEDF8"></path>

<!-- Animation to fill half an arc -->
<path class="progress" d="M5 50a45 45 0 1 1 90 0" stroke="#f00" stroke-dasharray="142" stroke-dashoffset="142">
<animate attributeName="stroke-dashoffset" from="142" to="71" dur="4s" fill="freeze" />
</path>
</g>

<defs>
<pattern id="image" x="0%" y="0%" height="100%" width="100%" viewBox="0 0 60 60">
<image x="0%" y="0%" width="60" height="60" xlink:href="https://via.placeholder.com/150x150"></image>
</pattern>
</defs>


<circle fill="url(#image)" id='case_progress__prog_fill' class="case_progress__prog" cx="0" cy="0" r="8" fill="#999" stroke="#fff" stroke-width="1" >
<!-- Animation of movement of a circle with an image -->
<animateMotion begin="0s" dur="4s" fill="freeze">
<mpath xlink:href="#pfad" />
</animateMotion>
</circle>

</svg>
</div>

How to animate fill instead of path in an SVG progress bar

You can use a mask and move it upward from the bottom on the heart as donations are made. [EDIT]:Included is an interval timer to animate the fill.
See example below:

<!DOCTYPE HTML><html><body><div style='width:200px;height:200px;'>  <svg  x="0px" y="0px" viewBox="0 0 100 100" >  <defs>    <mask id="heart">        <path fill=white d="M81.495,13.923c-11.368-5.261-26.234-0.311-31.489,11.032C44.74,13.612,29.879,8.657,18.511,13.923  C6.402,19.539,0.613,33.883,10.175,50.804c6.792,12.04,18.826,21.111,39.831,37.379c20.993-16.268,33.033-25.344,39.819-37.379  C99.387,33.883,93.598,19.539,81.495,13.923z"/>    </mask></defs>  <rect id=heartRect x=0 y="100%"  fill=red width="100%" height="100%"  mask="url(#heart)" />  <path id=heartPath stroke="red" fill=none stroke-width=3 d="M81.495,13.923c-11.368-5.261-26.234-0.311-31.489,11.032C44.74,13.612,29.879,8.657,18.511,13.923  C6.402,19.539,0.613,33.883,10.175,50.804c6.792,12.04,18.826,21.111,39.831,37.379c20.993-16.268,33.033-25.344,39.819-37.379  C99.387,33.883,93.598,19.539,81.495,13.923z"/>  </svg></div> <button onClick=donateAnimate()>Donate Animate()</button> <script>//---button---function donateAnimate(){var iT = setInterval(donate, 50 )var Donations=0function donate(){     if(Donations>=1)    clearInterval(iT);    var bb=heartPath.getBBox()    var bby=bb.y    var bbh=bb.height    //---bottom of heart---    var heartBase=bby+bbh
if(Donations<1) { Donations+=.05 var percent=(1-Donations)*heartBase heartRect.setAttribute("y",percent) }
}
} </script></body></html>

circle progress bar css

Here is my attempt. There is a lot of divs, but I didn't had the time to try to reduce them.

Basically, it plays with offsets between one circle and the other.

.container {  width: 400px;  height: 400px;  position: relative;  background-color: black;}
.left { position: absolute; width: 50%; height: 100%; right: 0px; overflow: hidden;}
.moving { animation: rotatel 8s 1s linear forwards; /* to keep both animations the same */}
.left .moving { position: absolute; width: calc(200% - 70px); height: calc(100% - 70px); right: 15px; top: 20px; border: 20px solid transparent; border-top-color: red; border-right-color: red; border-radius: 50%; transform: rotate(-135deg);}
@keyframes rotatel { from {transform: rotate(-135deg);} 50%, 100% {transform: rotate(45deg);}}
.right { position: absolute; width: 50%; height: 100%; left: 0px; overflow: hidden;}
.right .moving { position: absolute; width: calc(200% - 50px); height: calc(100% - 50px); left: 10px; top: 0px; border: 20px solid transparent; border-top-color: red; border-right-color: red; border-radius: 50%; transform: rotate(45deg); animation-name: rotater;}
@keyframes rotater { 0%, 50% {transform: rotate(45deg);} 100% {transform: rotate(225deg);}}.inner { position: absolute; width: calc(100% - 40px); height: calc(100% - 40px); border-radius: 50%; background-color: white; left: 20px; top: 20px; border: red solid 1px; background-color: black;}
<div class="container"><div class="left">    <div class="moving"></div></div><div class="right">    <div class="moving"></div></div><div class="inner"></div></div>

SVG progress bar

First off, you want to use clip-path, or set the mask fill to white for 100% opacity: mask is used as a greyscale alpha channel and the red fill color causes the opacity change.

As for the stroke, you want to add it as a separate element that is not affected by the clipping. (You can probably re-use the path with defs and use, I just copy-pasted it here)

#progressMove {  transition: .3s y;}#progressMove:hover {  y: 60%;}
<svg id="kenseoProgress" width="79.36px" height="93.844px" viewBox="0 0 79.36 93.844">  <defs>    <clipPath id="bubbleKenseo">      <path d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />    </clipPath>  </defs>  <path stroke="black" stroke-width="1" fill="transparent" d="M50,2C30-4,8,7,2,28c-6,20,5,42,26,48h0l-4,15l33-18c0-0,0-0,1-0l0-0l-0-0c8-4,15-12,17-22C83,30,71,8,50,2z" />  <g x="0" y="0" width="79.36px" height="93.844px" clip-path="url(#bubbleKenseo)" height="100">    <rect id="progressMove" x="0" y="0%" width="100%" height="100%" fill="blue" stroke="black" />  </g></svg>

How to implement a continuous motion illusion in SVG?

I am using a path twice:#a and #b. Both #a and #b have stroke-dasharray: 1 but #b id offset stroke-dashoffset: 1;

I'm animating the stroke-dashoffset for both #a and #b.

use {
stroke-dasharray: 1;
}
#a {
stroke: green;
animation: dasha 5s linear infinite;
}
#b {
stroke: DarkSeaGreen;
stroke-dashoffset: 1;
animation: dashb 5s linear infinite;
}
@keyframes dasha {
to {
stroke-dashoffset: -54.66;
}
}
@keyframes dashb {
to {
stroke-dashoffset: -53.66;
}
}
<svg viewBox='0 0 24 24' width="200"><title>gesture</title>
<defs><path id="thePath" fill="none" d='M4.59 6.89c.7-.71 1.4-1.35 1.71-1.22.5.2 0 1.03-.3 1.52-.25.42-2.86 3.89-2.86 6.31 0 1.28.48 2.34 1.34 2.98.75.56 1.74.73 2.64.46 1.07-.31 1.95-1.4 3.06-2.77 1.21-1.49 2.83-3.44 4.08-3.44 1.63 0 1.65 1.01 1.76 1.79-3.78.64-5.38 3.67-5.38 5.37 0 1.7 1.44 3.09 3.21 3.09 1.63 0 4.29-1.33 4.69-6.1h2.46'></path>
</defs>
<use id="a" xlink:href="#thePath" />
<use id="b" xlink:href="#thePath" />
</svg>


Related Topics



Leave a reply



Submit