首页 文章

使用javascript在svg中设置动画半径

提问于
浏览
0

我正在尝试用香草JS创建一个svg圆环图 . 我能够为填充笔划设置动画,但是我想要一个从中心开始的指针,然后转到圆周以与圆环的值一起动画 . 我可以写一个函数来绘制指针,但不能想出一些东西来动画它 .

Donut animation

我的JS类似于:

var svgCircle = document.querySelector('.progress');
var progressValue = document.querySelector('.progress__value');

var RADIUS = 108;
var CIRCUMFERENCE = 2 * Math.PI * RADIUS;

function progress(value) {
  var progress = value / 100;
  var dashoffset = CIRCUMFERENCE * (1 - progress);
  var innerCircle = drawInnerCircle();
  var handOfTheKing = drawHand(value);

  progressValue.style.strokeDashoffset = dashoffset;
  svgCircle.appendChild(handOfTheKing);

  svgCircle.appendChild(innerCircle);

}

function drawInnerCircle () {
  var innerCircle = document.createElementNS('http://www.w3.org/2000/svg','circle');
  innerCircle.setAttribute("id", "innerCircle");
  innerCircle.setAttribute("cx", "120");
  innerCircle.setAttribute("cy", "120");
  innerCircle.setAttribute("r", '10');
  innerCircle.setAttribute("stroke-width", '1');
  innerCircle.setAttribute("stroke", '#000');
  innerCircle.setAttribute("fill", '#fff');
  return innerCircle;
}

function drawHand(per) {
  var anglePartition = 2*Math.PI/100;
  var percentageWithOffset = per;
  var x = 120 + (120 * Math.cos(anglePartition * percentageWithOffset));
  var y = 120 + 120 * Math.sin(anglePartition * percentageWithOffset);
  var clockHand = document.createElementNS('http://www.w3.org/2000/svg','path');
  clockHand.setAttribute("id", "clockHand");
  clockHand.setAttribute("d", "M 120 120 L" + x + " " + y);
  clockHand.setAttribute("stroke", "black");
  clockHand.setAttribute("stroke-width", '1');
  return clockHand;
}

Here's a fiddle for this.

有人可以帮忙吗? TIA

编辑:我想要帮助动画箭头手,而不是甜甜圈填充笔画 .

What's needed

1 回答

  • 1

    您正在尝试混合两种不同类型的动画 . strokeDashoffset可以通过css动画来控制,其中时钟指针的路径需要线性解释函数,它将一次计算半径,这在css中无法完成 . 虽然这个问题可能有不同的解决方案 . 我已经提出了这个解决方案,看看它是否有帮助 .

    我正在使用requestAnimationFrame执行与通过css转换执行的操作相同的操作 . 我已将InOutQuad作为缓动函数(https://github.com/component/ease/blob/master/index.js) . 随意使用您喜欢的任何缓动功能 .

    var control = document.getElementById('control');
        var svgCircle = document.querySelector('.progress');
        var progressValue = document.querySelector('.progress__value');
    
        var RADIUS = 108;
        var CIRCUMFERENCE = 2 * Math.PI * RADIUS;
        progressValue.style.strokeDashoffset = CIRCUMFERENCE;    
    
        function drawInnerCircle () {
    
          var innerCircle = document.createElementNS('http://www.w3.org/2000/svg','circle');
          innerCircle.setAttribute("id", "innerCircle");
          innerCircle.setAttribute("cx", "120");
          innerCircle.setAttribute("cy", "120");
          innerCircle.setAttribute("r", '10');
          innerCircle.setAttribute("stroke-width", '1');
          innerCircle.setAttribute("stroke", '#000');
          innerCircle.setAttribute("fill", '#fff');
          return innerCircle;
        }
    
       progressValue.style.strokeDasharray = CIRCUMFERENCE;
    
        var starttime
    
        function plot(timestamp, dist, duration){
          var timestamp = timestamp || new Date().getTime();
          var runtime = timestamp - starttime;
          var progress = runtime / duration;
          progress = inOutQuad(Math.min(progress, 1));
    
          //clock handle animation
          var anglePartition = 2*Math.PI/100;
          var percentageWithOffset = (dist * progress);
          var x = 120 + (120 * Math.cos(anglePartition * percentageWithOffset));
          var y = 120 + 120 * Math.sin(anglePartition * percentageWithOffset);
          var clockHand = document.getElementById('clockHand')
            clockHand.setAttribute("d", "M 120 120 L" + x + " " + y);
          clockHand.setAttribute("stroke", "black");
          clockHand.setAttribute("stroke-width", '1');
    
          //arc animation
          progressValue.style.strokeDashoffset = CIRCUMFERENCE * (1 - (progress * dist /100));
          if (runtime < duration){ 
            requestAnimationFrame(function(timestamp){ 
              plot(timestamp, dist, duration)
            })
          }
        }
        setTimeout(function(){
             requestAnimationFrame(function(timestamp){
            starttime = timestamp || new Date().getTime();
            var innerCircle = drawInnerCircle();
            svgCircle.appendChild(innerCircle);
            plot(timestamp, 60, 1000);
          })
        }, 500)
    
        function inOutQuad(n){
                n *= 2;
            if (n < 1) return 0.5 * n * n;
            return - 0.5 * (--n * (n - 2) - 1);
            };
    

    这是一个小提琴https://jsfiddle.net/Ljvbx1hz/

相关问题