Nicla Marino
Nicla Marino

Reputation: 97

SVG circle with multiple origin for stroke animation

I have a simple donut graph with fill-in animation. The problem is that I get two separate paths. (Es. 10% bar gives me 0-10% and then space and then another 10%.

I have tried playing around with the different variables but I can't figure out what I am doing wrong, any help? I have used this: https://codepen.io/matttherat/pen/EeMaEw?editors=1100

Here's a screen:

a busy cat

.svg-item {
  flex: 1;
  font-size: 16px;
  max-width: 120px;
  animation: donutfade 1s;
  margin: 0 auto;
}

.data-des {
  font-size: 0.7em;
  display: block;
  font-weight: bold;
  text-align: center;
  margin-top: 10px;
}

@keyframes donutfade {
  /* this applies to the whole svg item wrapper */
  0% {
    opacity: 0.2;
  }
  100% {
    opacity: 1;
  }
}

.donut-ring-ext {
  stroke: #50b180;
}

.donut-segment {
  transform-origin: center;
}

.donut-segment-2 {
  stroke: #a8df8a;
  animation: donut1 1s;
}

.donut-segment-3 {
  stroke: #a8df8a;
  animation: donut2 1s;
}

.donut-segment-4 {
  stroke: #a8df8a;
  animation: donut3 1s;
}

.donut-percent {
  color: #3c8560;
  animation: donutfadelong 1s;
}

@keyframes donutfadelong {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

@keyframes donut1 {
  0% {
    stroke-dasharray: 0 100;
  }
  100% {
    stroke-dasharray: 10 90;
  }
}

@keyframes donut2 {
  0% {
    stroke-dasharray: 0, 100;
  }
  100% {
    stroke-dasharray: 20, 80;
  }
}

@keyframes donut3 {
  0% {
    stroke-dasharray: 0, 100;
  }
  100% {
    stroke-dasharray: 50, 50;
  }
}

.donut-label {
  font-size: 0.28em;
  font-weight: 700;
  line-height: 1;
  fill: #000;
  transform: translateY(0.25em);
}

.donut-percent {
  font-size: 0.5em;
  line-height: 1;
  transform: translateY(0.5em);
  font-weight: 100;
}

.donut-data {
  font-size: 0.12em;
  line-height: 1;
  transform: translateY(0.5em);
  text-align: center;
  text-anchor: middle;
  color: #666;
  fill: #666;
  animation: donutfadelong 1s;
}
<div class="svg-item">
  <svg width="100%" height="100%" viewBox="0 0 40 40" class="donut">
                                <circle
                                    class="donut-hole"
                                    cx="20"
                                    cy="20"
                                    r="15.91549430918954"
                                    fill="#fff"
                                ></circle>
                                <circle
                                    class="donut-ring-ext"
                                    cx="20"
                                    cy="20"
                                    r="19"
                                    fill="transparent"
                                    stroke-width="2"
                                ></circle>
                                <circle
                                    class="donut-segment donut-segment-2"
                                    cx="20"
                                    cy="20"
                                    r="22"
                                    fill="transparent"
                                    stroke-width="2"
                                    stroke-dasharray="10 90"
                                    stroke-dashoffset="-5"
                                ></circle>
                                <g class="donut-text donut-text-1">
                                    <text y="50%" transform="translate(0, 2)">
                                        <tspan
                                            x="50%"
                                            text-anchor="middle"
                                            class="donut-percent"
                                        >
                                            10%
                                        </tspan>
                                    </text>
                                </g>
                                <span class="data-des">Amet dolorem sit</span>
                            </svg>
</div>

Upvotes: 1

Views: 1015

Answers (1)

enxaneta
enxaneta

Reputation: 33034

You need to animate the stroke-dashoffset attribute. At the beginning stroke-dasharay = the path's total length (calculated with .getTotalLength()). Since you are using only one value the dashes and the gaps are of equal length.

stroke-dasharray="137.35"

Also the stroke-dashoffset="137.35". This means that you don't see the dash. In this moment your stroke is the gap.

Next you are animating the stroke-dashoffset. If you want to see 10% of the dash yoi need to animate the stroke-dashoffset from 100% to 90% i.e

 100% {
    stroke-dashoffset: 123.6;
  }

I hope it helps.

.svg-item {
  flex: 1;
  font-size: 16px;
  max-width: 400px;
  margin: 0 auto;
}

.data-des {
  font-size: 0.7em;
  display: block;
  font-weight: bold;
  text-align: center;
  margin-top: 10px;
}

.donut-ring-ext {
  stroke: #50b180;
}

.donut-segment {
  transform-origin: center;
}

.donut-segment-2 {
  stroke: #a8df8a;
  animation: donut1 1s forwards;
}

.donut-segment-3 {
  stroke: #a8df8a;
  animation: donut2 1s;
}

.donut-segment-4 {
  stroke: #a8df8a;
  animation: donut3 1s;
}

.donut-percent {
  color: #3c8560;
  animation: donutfadelong 1s;
}



@keyframes donut1 {
  100% {
    stroke-dashoffset: 123.6;
  }
}


.donut-label {
  font-size: 0.28em;
  font-weight: 700;
  line-height: 1;
  fill: #000;
  transform: translateY(0.25em);
}

.donut-percent {
  font-size: 0.5em;
  line-height: 1;
  transform: translateY(0.5em);
  font-weight: 100;
}

.donut-data {
  font-size: 0.12em;
  line-height: 1;
  transform: translateY(0.5em);
  text-align: center;
  text-anchor: middle;
  color: #666;
  fill: #666;
  animation: donutfadelong 1s;
}

svg{border:1px solid}
<div class="svg-item">
  <svg viewBox="-30 -10 100 100" class="donut">
  <g transform="rotate(-90 20 20)">
                                <circle
                                    class="donut-hole"
                                    cx="20"
                                    cy="20"
                                    r="15.91549430918954"
                                    fill="#f00"
                                ></circle>
                                <circle
                                    class="donut-ring-ext"
                                    cx="20"
                                    cy="20"
                                    r="19"
                                    fill="transparent"
                                    stroke-width="2"
                                ></circle>
                                <circle 
                                    class="donut-segment donut-segment-2"
                                    cx="20"
                                    cy="20"
                                    r="22"
                                    fill="transparent"
                                    stroke-width="2"
                                    stroke-dasharray="137.35"
                                    stroke-dashoffset="137.35"
                                ></circle></g>
                                <g class="donut-text donut-text-1">
                                    <text y="50%" transform="translate(0, 2)">
                                        <tspan
                                            x="50%"
                                            text-anchor="middle"
                                            class="donut-percent"
                                        >
                                            10%
                                        </tspan>
                                    </text>
                                </g>
                                <span class="data-des">Amet dolorem sit</span>
                            </svg>
</div>

Upvotes: 1

Related Questions