Animation 对圆弧的多个起始角和终止角进行随机化并设置动画

Animation 对圆弧的多个起始角和终止角进行随机化并设置动画,animation,d3.js,tween,Animation,D3.js,Tween,我正在尝试创建一个视频,它是对演示的修改。在其中,我需要一个数据数组来定义每个圆弧的颜色和一般半径,并且在一个间隔上,开始和结束角度都应该缓慢地设置动画。但我认为我定义每个弧的方式会导致事情过于活跃 HTML 不是将每个圆弧从起始角度平滑地设置为新角度的动画,而是将整个视觉多次跳到新状态 如何配置此功能,以使每个圆弧平滑地从旧角度过渡到新角度?这里有一些问题 您的arc函数将在每次调用时返回随机半径,这不是我认为您想要的。可以将圆弧从一个内/外半径过渡到下一个内/外半径,但为了简单起见,假设每个

我正在尝试创建一个视频,它是对演示的修改。在其中,我需要一个数据数组来定义每个圆弧的颜色和一般半径,并且在一个间隔上,开始和结束角度都应该缓慢地设置动画。但我认为我定义每个弧的方式会导致事情过于活跃

HTML

不是将每个圆弧从起始角度平滑地设置为新角度的动画,而是将整个视觉多次跳到新状态


如何配置此功能,以使每个圆弧平滑地从旧角度过渡到新角度?

这里有一些问题

  • 您的arc函数将在每次调用时返回随机半径,这不是我认为您想要的。可以将圆弧从一个内/外半径过渡到下一个内/外半径,但为了简单起见,假设每个路径最初只获得一个随机半径

  • 为了从一对旧的开始/结束角度过渡到新的开始/结束角度,您需要将当前角度存储在某个位置。我们将它存储在一个文件夹中,该文件夹将绑定到每个路径

  • 因为每条路径都有不同的内/外半径,所以我们还需要为每个线段使用不同的圆弧函数

  • 此处的工作代码:

        var tau = 2 * Math.PI; // http://tauday.com/tau-manifesto
        var overlap = 50;
        var currentSegment = d3.local();
        var segmentRadius = d3.local();
    
        var jsonArcs = [
          { "base_radius": 370, "color" : "red"},
          { "base_radius": 330, "color" : "orange"},
          { "base_radius": 290, "color" : "yellow"},
          { "base_radius": 250, "color" : "green"},
          { "base_radius": 210, "color" : "blue" },
          { "base_radius": 170, "color" : "purple"},
          { "base_radius": 130, "color" : "black"},
          { "base_radius": 90, "color" : "red"}
        ];
    
        var arc = d3.arc()
            .innerRadius(function() { return segmentRadius.get(this).innerRadius })
            .outerRadius(function() { return segmentRadius.get(this).outerRadius });
    
        var center_def = d3.arc()
            .innerRadius(0)
            .outerRadius(60)
            .startAngle(0);
    
        var svg = d3.select("svg"),
            width = +svg.attr("width"),
            height = +svg.attr("height"),
            g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
    
        var path = g.selectAll("path")
            .data(jsonArcs)
            .enter().append("path")
            .attr("fill", function(d, i) { return d.color; })
            .each(function(d) {
              var angles = randomAngles();
              d.startAngle = angles.startAngle;
              d.endAngle = angles.endAngle;
              segmentRadius.set(this, {
                innerRadius: d.base_radius - overlap * Math.random(),
                outerRadius: d.base_radius + overlap * Math.random()
              });
            })
            .attr("d", arc)
            .each(function(d) {currentSegment.set(this, d)});
    
        var center = g.append("path")
            .datum({endAngle: tau})
            .style("fill", "black")
            .attr("d", center_def);
    
        d3.interval(function() {
          path.transition()
              .duration(750)
              .attrTween("d", arcTween);
        }, 2500);
    
        function arcTween() {
          var thisPath = this;
          var interpolate = d3.interpolate(currentSegment.get(this), randomAngles());
          currentSegment.set(this, interpolate(0));
    
          return function(t) {
            return arc.call(thisPath, interpolate(t));
          };
        }
        function randomAngles() {
          var angles = [Math.random() * tau, Math.random() * tau].sort();
          return {startAngle: angles[0], endAngle: angles[1]};
        }
    
    请注意有关更改代码的几点:

  • 在设置“d”属性之前,我在路径上的每次调用中设置了随机初始角度
  • 我将段半径存储在同一链末端的segmentRadius d3.local变量中,并且在调用转换设置每个插值之后
  • 在转换函数中,我需要调用arc来保留路径的“this”,以便在检索segmentRadius时,arc.innerRadius中的“this”是正确的
  • d3.interpolate可以愉快地处理对象,而不仅仅是数字

  • 如果您想了解更多信息,我有一个类似的例子,我一直在研究。

    这里有一些问题

  • 您的arc函数将在每次调用时返回随机半径,这不是我认为您想要的。可以将圆弧从一个内/外半径过渡到下一个内/外半径,但为了简单起见,假设每个路径最初只获得一个随机半径

  • 为了从一对旧的开始/结束角度过渡到新的开始/结束角度,您需要将当前角度存储在某个位置。我们将它存储在一个文件夹中,该文件夹将绑定到每个路径

  • 因为每条路径都有不同的内/外半径,所以我们还需要为每个线段使用不同的圆弧函数

  • 此处的工作代码:

        var tau = 2 * Math.PI; // http://tauday.com/tau-manifesto
        var overlap = 50;
        var currentSegment = d3.local();
        var segmentRadius = d3.local();
    
        var jsonArcs = [
          { "base_radius": 370, "color" : "red"},
          { "base_radius": 330, "color" : "orange"},
          { "base_radius": 290, "color" : "yellow"},
          { "base_radius": 250, "color" : "green"},
          { "base_radius": 210, "color" : "blue" },
          { "base_radius": 170, "color" : "purple"},
          { "base_radius": 130, "color" : "black"},
          { "base_radius": 90, "color" : "red"}
        ];
    
        var arc = d3.arc()
            .innerRadius(function() { return segmentRadius.get(this).innerRadius })
            .outerRadius(function() { return segmentRadius.get(this).outerRadius });
    
        var center_def = d3.arc()
            .innerRadius(0)
            .outerRadius(60)
            .startAngle(0);
    
        var svg = d3.select("svg"),
            width = +svg.attr("width"),
            height = +svg.attr("height"),
            g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
    
        var path = g.selectAll("path")
            .data(jsonArcs)
            .enter().append("path")
            .attr("fill", function(d, i) { return d.color; })
            .each(function(d) {
              var angles = randomAngles();
              d.startAngle = angles.startAngle;
              d.endAngle = angles.endAngle;
              segmentRadius.set(this, {
                innerRadius: d.base_radius - overlap * Math.random(),
                outerRadius: d.base_radius + overlap * Math.random()
              });
            })
            .attr("d", arc)
            .each(function(d) {currentSegment.set(this, d)});
    
        var center = g.append("path")
            .datum({endAngle: tau})
            .style("fill", "black")
            .attr("d", center_def);
    
        d3.interval(function() {
          path.transition()
              .duration(750)
              .attrTween("d", arcTween);
        }, 2500);
    
        function arcTween() {
          var thisPath = this;
          var interpolate = d3.interpolate(currentSegment.get(this), randomAngles());
          currentSegment.set(this, interpolate(0));
    
          return function(t) {
            return arc.call(thisPath, interpolate(t));
          };
        }
        function randomAngles() {
          var angles = [Math.random() * tau, Math.random() * tau].sort();
          return {startAngle: angles[0], endAngle: angles[1]};
        }
    
    请注意有关更改代码的几点:

  • 在设置“d”属性之前,我在路径上的每次调用中设置了随机初始角度
  • 我将段半径存储在同一链末端的segmentRadius d3.local变量中,并且在调用转换设置每个插值之后
  • 在转换函数中,我需要调用arc来保留路径的“this”,以便在检索segmentRadius时,arc.innerRadius中的“this”是正确的
  • d3.interpolate可以愉快地处理对象,而不仅仅是数字

  • 如果您想了解更多信息,我有一个类似的例子,我一直在研究。

    相关:但我不知道如何使用提供的数据调用多个圆弧相关:但我不知道如何使用提供的数据调用多个圆弧谢谢!这很有道理。我一直在努力将每次通话的半径随机化,但我没有想到存储以前的状态。我也不太熟悉“每个”谢谢!这很有道理。我一直在努力将每次通话的半径随机化,但我没有想到存储以前的状态。我对“每个”也不够熟悉
        var tau = 2 * Math.PI; // http://tauday.com/tau-manifesto
        var overlap = 50;
        var currentSegment = d3.local();
        var segmentRadius = d3.local();
    
        var jsonArcs = [
          { "base_radius": 370, "color" : "red"},
          { "base_radius": 330, "color" : "orange"},
          { "base_radius": 290, "color" : "yellow"},
          { "base_radius": 250, "color" : "green"},
          { "base_radius": 210, "color" : "blue" },
          { "base_radius": 170, "color" : "purple"},
          { "base_radius": 130, "color" : "black"},
          { "base_radius": 90, "color" : "red"}
        ];
    
        var arc = d3.arc()
            .innerRadius(function() { return segmentRadius.get(this).innerRadius })
            .outerRadius(function() { return segmentRadius.get(this).outerRadius });
    
        var center_def = d3.arc()
            .innerRadius(0)
            .outerRadius(60)
            .startAngle(0);
    
        var svg = d3.select("svg"),
            width = +svg.attr("width"),
            height = +svg.attr("height"),
            g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
    
        var path = g.selectAll("path")
            .data(jsonArcs)
            .enter().append("path")
            .attr("fill", function(d, i) { return d.color; })
            .each(function(d) {
              var angles = randomAngles();
              d.startAngle = angles.startAngle;
              d.endAngle = angles.endAngle;
              segmentRadius.set(this, {
                innerRadius: d.base_radius - overlap * Math.random(),
                outerRadius: d.base_radius + overlap * Math.random()
              });
            })
            .attr("d", arc)
            .each(function(d) {currentSegment.set(this, d)});
    
        var center = g.append("path")
            .datum({endAngle: tau})
            .style("fill", "black")
            .attr("d", center_def);
    
        d3.interval(function() {
          path.transition()
              .duration(750)
              .attrTween("d", arcTween);
        }, 2500);
    
        function arcTween() {
          var thisPath = this;
          var interpolate = d3.interpolate(currentSegment.get(this), randomAngles());
          currentSegment.set(this, interpolate(0));
    
          return function(t) {
            return arc.call(thisPath, interpolate(t));
          };
        }
        function randomAngles() {
          var angles = [Math.random() * tau, Math.random() * tau].sort();
          return {startAngle: angles[0], endAngle: angles[1]};
        }