【问题标题】:Animate radius in svg with javascript用javascript在svg中动画半径
【发布时间】:2018-01-17 01:35:44
【问题描述】:

我正在尝试使用 vanilla JS 创建一个 svg 圆环图。我能够为填充描边设置动画,尽管我想要一个从中心开始并到圆周以与甜甜圈的值一起动画的指针。我可以编写一个函数来绘制指针,但无法想出一些动画。

我的 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

编辑: 我需要动画箭头手的帮助,而不是甜甜圈填充笔划。

【问题讨论】:

标签: javascript css animation svg donut-chart


【解决方案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/的小提琴

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-20
    • 2020-01-29
    • 2021-09-28
    • 1970-01-01
    相关资源
    最近更新 更多