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

问题描述 投票:1回答:1

我正在尝试使用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>
javascript html5 svg
1个回答
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中的中风动画,请阅读qazxsw poi

© www.soinside.com 2019 - 2024. All rights reserved.