Reputation: 33
I created loading spinner in SVG, but animation-duration is not accurate. For example:
I'm desperate and I don't know where there may be a mistake. Can you help me?
Screen of spinner #1
Screen of spinner #2 - later
<svg class="circle">
<circle cx="23" cy="23" r="20"/>
</svg>
Less:
@spinnerSize: 46;
svg.spinner {
display: block;
width: (@spinnerSize + 0px);
height: (@spinnerSize + 0px);
x: 0px;
y: 0px;
background: url("../images/ico_timer_small.png") center center no-repeat;
circle {
fill: transparent;
stroke: #027eff;
stroke-width: 3;
stroke-dasharray: (3.14 * @spinnerSize);
transform-origin: (0.5px * @spinnerSize) (0.5px * @spinnerSize) 0;
transform: rotate(-90deg);
animation-name: spinner;
animation-timing-function: linear;
animation-duration: 30s;
stroke-linecap: butt;
}
}
@keyframes spinner {
from {
stroke-dashoffset: (3.14 * @spinnerSize);
}
to {
stroke-dashoffset: 0;
}
}
Upvotes: 3
Views: 450
Reputation: 89770
The stroke-dasharray
value should be equal to the circumference of the circle for this animation to work properly. The circle's radius is only 20 and so the circumference (2 * PI * radius) is equal to 125.66 but in the Less code you have set the diameter (@spinnerSize
) as 46 and because of this, the stroke-dasharray
has a computed value of 144.44 (greater than circumference of circle).
For a value to go from 0 to 144.44 in 30s, it must be incremented (approximately) by 4.81 per second and so by the time it reaches the 26s mark, the value becomes (26 * 4.81) = 125.81 (approximately). Since this value is greater than the circumference, it looks like the animation has completed ahead of time whereas in reality it is still animating the value until it reaches 144.44.
In the below snippet, I've set 125
as the final value and it runs as expected for 30 seconds. In Less code, you need to calculate stroke-dasharray
based on two times the radius of the circle. Do not directly modify the value of @spinnerSize
variable because that would modify a few other properties and end up affecting the display of the SVG circle.
svg.spinner {
display: block;
width: 46px;
height: 46px;
/*x: 0px;
y: 0px;*/
background: url("../images/ico_timer_small.png") center center no-repeat;
}
svg.spinner circle {
fill: transparent;
stroke: #027eff;
stroke-width: 3;
stroke-dasharray: 125;
transform-origin: 23px 23px 0;
transform: rotate(-90deg);
animation-name: spinner;
animation-timing-function: linear;
animation-duration: 30s;
stroke-linecap: butt;
}
@keyframes spinner {
from {
stroke-dashoffset: 125;
}
to {
stroke-dashoffset: 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<svg class="spinner">
<circle cx="23" cy="23" r="20" />
</svg>
1. Prefix-free library is used in snippet only to avoid browser prefixes.
2. I've used the compiled CSS generated by the Online Less compiler at Less2CSS.
Upvotes: 6