d3.js D3JS:设置2圆弧圆环的动画

vom3gejh  于 2022-11-12  发布在  其他
关注(0)|答案(2)|浏览(196)

我是D3JS的新手,我做了一个2弧的甜甜圈(我的数据只有两个值)。我试图弄清楚如何动画他们,使最大的路径得到“自我绘制”第一,然后最小的一个也得到自我绘制。
我知道这可以通过将起始Angular 设置为0来实现,然后使用D3js attrTween()并使用所需的最终Angular 进行播放。但由于我无法自己声明最终Angular ,它取决于数据,而且由于我对djse的了解非常少,我还无法实现它。
这是我的JS代码:

var width = 100,
  height = 100,
  radius = (Math.min(width, height) / 2);

function drawDonut(dataa, divchart) {
  var sym = "%"

  var color = ["#00338D", "#BC204B"];

  var pie = d3.pie()
    .value(function(d) {
      return d
    })(dataa);

  var arc = d3.arc()
    .outerRadius(radius - 10)
    .innerRadius(radius - (radius / 1.9));

  var labelArc = d3.arc()
    .outerRadius(radius - 31)
    .innerRadius(radius - 31);

  var svg = d3.select(divchart)
    .append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", "translate(" + 50 + "," + 50 + ")");

  var g = svg.selectAll("arc")
    .data(pie)
    .enter().append("g")
    .attr("class", "arc");

  g.append("path")
    .attr("d", arc)
    .data(color)
    .style("fill", function(d) {
      return d
    });

  g.append("g")
    .attr("transform", "translate(-17,-17) scale(0.7)")
    .html(myGroup);    
}
50pmv0ei

50pmv0ei1#

使用来自previous postattrTween数据作为参考,下面是一个应用了大路径优先动画的代码片段
第一个

相关变更:

  1. AttrTween函数
function arcTween(d) {
  var i = d3.interpolate(d.startAngle, d.endAngle);
  return function (t) {
    d.endAngle = i(t);
    return arc(d);
  }
}

1.对路径使用上述方法,沿着在过渡中使用延迟,顺便说一句,延迟用于按顺序动画化路径。

g.append("path")
 .style("fill", function(d, i) {
    return color[i];
 })
 .transition().delay(function (d, i) { return i*800}).duration(800)
 .attrTween("d", arcTween);

1.按降序对数据进行排序,以首先绘制最大的弧。

// sort data
data = data.sort(function (a, b) { return b-a; });
w9apscun

w9apscun2#

根据Shashank的回答,我想提出一个修改

  • 不对data进行排序,因为顺序看起来很重要(d[0] == man,d[1] == woman),并且弧线是按顺序着色的
// sort data
//data = data.sort(function (a, b) { return b-a; });
  • 饼图生成器也不应根据值对数据进行排序
var pie = d3.pie()
  .sortValues(null) // both null means NO sort
  .value(function(d) {
    return d
  })(data);
  • 在Shashanks回答中,两个部分都使用easeCubic制作动画,每个部分(小或大)需要800 ms。要获得恒定角速度动画,我们必须根据部分的startAngleendAngle设置延迟和持续时间。过渡必须设置为easeLinear。在演示中,我将完整动画设置为5000 ms。
var msecPerRad = 5000 / (2*Math.PI);
g.append("path")
  .style("fill", function(d, i) { return color[i]; })
  .transition()
  .ease(d3.easeLinear)
  .delay(function (d) { return d.startAngle * msecPerRad;})
  .duration(function (d) { return (d.endAngle - d.startAngle) * msecPerRad;})
  .attrTween("d", arcTween);

使用线性缓动的示例
第一个
如果你想用easeCubic来完成完整的Angular 动画,这需要更多的数学运算。主要原因是两个弧段都是独立的过渡。这应该适用于2个以上的弧段。
它只适用于单调递增缓动函数,不适用于反弹、弹性和返回(进/出)等函数。

function easeInverse(ease) {
    return function(e) {
      var min = 0, max = 1;
      while (max - min > 1e-3) {
        var mid = (max + min) * 0.5;
        emid = ease(mid);
        if (emid > e) { max = mid; }
        else { min = mid; }
      }
      return max;
    }
  }
  var inverseCubic = easeInverse(d3.easeCubic);
  var oneOver2Pi = 1.0 / (2*Math.PI);
  var total_msec = 5000;

  g.append("path")
    .style("fill", function(d, i) { return color[i]; })
    .transition()
    .ease(d3.easeLinear)
    .delay(function (d) { return total_msec * inverseCubic(d.startAngle * oneOver2Pi);})
    .duration(function (d) { return total_msec * (inverseCubic(d.endAngle * oneOver2Pi) - inverseCubic(d.startAngle * oneOver2Pi));})
    .attrTween("d", arcTween);

  function arcTween(d) {
    var i = d3.interpolate(inverseCubic(d.startAngle * oneOver2Pi), inverseCubic(d.endAngle * oneOver2Pi));
    return function (t) {
      d.endAngle = 2*Math.PI*d3.easeCubic(i(t));
      return arc(d);
    }
  }

完整圆形Angular 的“立方”缓动示例。
第一个

相关问题