使用SVG和JS创建30秒计时器显示

时间:2019-03-21 16:50:56

标签: javascript html5 svg

我正在尝试使用SVG和JS点创建30秒倒数计时器显示。这个想法很简单

  1. 将倒数时钟的表面绘制为SVG圆圈
  2. 在其内部以圆扇形绘制一条封闭的SVG路径
  3. 使用window.requestAnimationFrame每隔一秒更新一次扇区

我的努力如下所示。当它起作用时,最终结果远非平稳而令人信服。

  • 当花费的时间进入圆的第二象限时,该区域似乎膨胀超过了圆周
  • 当它位于第三和第四象限时,它似乎从圆周上脱离。

我在这里做错了什么,如何解决?

var _hold = {tickStart:0,stopTime:30,lastDelta:0};

String.prototype.format = function (args)
{
 var newStr = this,key;
 for (key in args) {newStr = newStr.replace('{' + key + '}',args[key]);}
 return newStr;
};

Boolean.prototype.intval = function(places)
{
 places = ('undefined' == typeof(places))?0:places; 
 return (~~this) << places;
};


function adjustSpent(timeStamp)
{
 if (0 === _hold.tickStart) _hold.tickStart = timeStamp;
 var delta = Math.trunc((timeStamp - _hold.tickStart)/1000);
 if (_hold.lastDelta < delta)
 {
  _hold.lastDelta = delta;
  var angle = 2*Math.PI*(delta/_hold.stopTime),
      dAngle = 57.2958*angle,
      cx = cy = 50,
      radius = 38,
      top = 12,
      x = cx + radius*Math.sin(angle),
      y = cy - radius*Math.cos(angle),
      large = (180 < dAngle).intval();
  
   var d = (360 <= dAngle)?"M50,50 L50,12 A38,38 1 0,1 51,12 z":"M50,50 L50,12 A38,38 1 {ll},1 {xx},{yy} z".format({ll:large,xx:x,yy:y});
   var spent = document.getElementById('spent');    
   if (spent) spent.setAttribute("d",d);
 }
 if (delta < _hold.stopTime) window.requestAnimationFrame(adjustSpent);
}

window.requestAnimationFrame(adjustSpent);
timer
{
 position:absolute;
 height:20vh;
 width:20vh;
 border-radius:100%;
 background-color:orange;
 left:calc(50vw - 5vh);
 top:15vh;
}

#clockface{fill:white;}
#spent{fill:#6683C2;}
<timer>
     <svg width="20vh" height="20vh" viewBox="0 0 100 100">
      <circle cx="50" cy="50" r="38" id="clockface"></circle>
      <path d="M50,50 L50,12 A38,38 1 0,1 51,12 z" id="spent"></path>
     </svg>
    </timer>

1 个答案:

答案 0 :(得分:1)

可能的解决方案是使用像这样的笔触动画:

蓝色圆圈的半径为38/2 = 19

蓝色圆圈的stroke-width为38,给人以38个单位的圆圈的错觉。

请看一下路径:它也是半径= 19的圆。

svg {
  border: 1px solid;
  height:90vh;
}
#clockface {
  fill: silver;
}
#spent {
  fill:none;
  stroke: #6683c2;
  stroke-width: 38px;
  stroke-dasharray: 119.397px;
  stroke-dashoffset: 119.397px;
  animation: dash 5s linear infinite;
}
  

@keyframes dash {
  to {
    stroke-dashoffset: 0;
  }
}
<svg  viewBox="0 0 100 100">
      <circle cx="50" cy="50" r="38" id="clockface"></circle>
      <path d="M50,31 A19,19 1 0,1 50,69 A19,19 1 0,1 50,31" id="spent"></path>
     </svg>

在这种情况下,我使用了CSS动画,但是您可以使用JavaScript控制stroke-dashoffset的值。

stroke-dasharray的值是使用spent.getTotalLength()

获得的

如果您不熟悉SVG中的笔画动画,请阅读How SVG Line Animation Works