d3js饼,刷新切片上的标签位置,转换饼图

时间:2013-11-07 14:21:40

标签: javascript d3.js

所以我正在尝试使用d3js饼图布局。我已经设法根据多个数据项进行馅饼转换。并在切片的中心放置每个项目的标签。

您可以在以下链接中查看我的示例:http://jsfiddle.net/ahbqP/

脚本如下所示:

var data_1 = [
              {"A": 43, "B": 10, "C":3, "D": 29, "E": 500},
              {"A": 20, "B": 2, "C":4, "D": 39, "E": 400 },
              {"A": 17, "B": 5, "C":6, "D": 19, "E": ""},
              {"A": 20, "B": 2, "C":2, "D": 69, "E": ""},
             ]

var width_1 = 500,
    height_1 = 400,
    radius_1 = Math.min(width_1, height_1) / 2;

var color_1 = d3.scale.category20c();

var pie_1 = d3.layout.pie()
    .value(function(d) { return d.A; })
    .sort(null);

var arc_1 = d3.svg.arc()
    .innerRadius(radius_1 - 100)
    .outerRadius(radius_1 - 20);

var svg_1 = d3.select(".pie_container_1").append("svg")
    .attr("width", width_1)
    .attr("height", height_1)
  .append("g")
    .attr("transform", "translate(" + width_1 / 2 + "," + height_1 / 2 + ")");

var path_1 = svg_1.datum(data_1).selectAll("path")
      .data(pie_1)
    .enter().append("g")
      .attr("class", "slice")
      .append("path")
      .attr("fill", function(d, i) { return color_1(i); })
      .attr("d", arc_1)
      .each(function(d) { this._current = d; }); // store the initial angles


var pText = svg_1.selectAll(".slice")
    .append("text")
    .attr("class","val")
    .attr("transform", function(d) {
                d.innerRadius = 0;
                d.outerRadius = radius_1;
                return "translate(" + arc_1.centroid(d) + ")";
            })
    .style("text-anchor", "middle")
    .data(data_1)
    .text(function(d) { return d.A + "%"; });

  d3.selectAll("input")
      .on("change", change_1);


function change_1() {
    var value_1 = this.value;
    // clearTimeout(timeout_1);
    pie_1.value(function(d) { return d[value_1]; }); // change the value function

    path_1 = path_1.data(pie_1); // compute the new angles

    var pathT = path_1.transition().duration(750).attrTween("d", arcTween_1); // redraw the arcs

    pText = svg_1.selectAll(".slice").select(".val").attr("transform", function(d) {
                d.innerRadius = 0;
                d.outerRadius = radius_1;
                return "translate("+ arc_1.centroid(d) +")";
            })
    .style("text-anchor", "middle")
    .data(data_1)
    .text(function(d) { 
                        if( value_1 == "E" && d.E != "" ){ return d.E + "%"; }
                        if( value_1 == "D" ){ return d.D + "%"; }
                        if( value_1 == "C" ){ return d.C + "%"; }
                        if( value_1 == "B" ){ return d.B + "%"; }
                        if( value_1 == "A" ){ return d.A + "%"; }

                      });
  }

// Store the displayed angles in _current.
// Then, interpolate from _current to the new angles.
// During the transition, _current is updated in-place by d3.interpolate.
function arcTween_1(a) {
  var i = d3.interpolate(this._current, a);
  this._current = i(0);
  return function(t) {
    return arc_1(i(t));
  };
}

除了一件事,一切正常。调用change_1函数后放置文本标签。他们留在以前的位置,因为我不知道如何设置新的位置值。在加载时,我正在设置它们:

.attr("transform", function(d) {
            d.innerRadius = 0;
            d.outerRadius = radius_1;
            return "translate(" + arc_1.centroid(d) + ")";
        })

但在change_1中调用相同的内容并不会移动它们。我假设我必须计算一些其他的质心值,但我不知道究竟是多少......

在change_1函数中使用新的弧线大小完全移动它们需要什么?

您可以编辑我的小提琴,欢迎任何帮助或建议......

1 个答案:

答案 0 :(得分:2)

在更改位置之前,您没有更新绑定到text元素的数据。因此,该职位未更新。

我已更新您的更改代码,以便在设置位置之前执行数据绑定。

pText = svg_1.selectAll(".val").data(pie_1).attr("transform", function(d) {
                d.innerRadius = 0;
                d.outerRadius = radius_1;
                return "translate("+ arc_1.centroid(d) +")";
            })

完成jsfiddle here。一般来说,如果您选择了随后添加的元素(即不选择.slice然后追加.val),那么最好的做法就像我在更新后的代码中所做的那样。这使得调试代码和理解正在发生的事情变得更加容易。

哦,将属性设置为副作用(即设置transform的函数内的半径)也不是好习惯。