Animate-duration is not accurate

巧了我就是萌 提交于 2019-12-12 15:14:21

问题


I created loading spinner in SVG, but animation-duration is not accurate. For example:

  • 30s animation-duration ~ 26s in real
  • 45s animation-duration ~ 38s in real
  • 60s animation-duration ~ 51s in real

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;
  }
}

回答1:


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.



来源:https://stackoverflow.com/questions/33922005/animate-duration-is-not-accurate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!