甜甜圈图:如何颠倒数字?

时间:2019-04-17 09:08:11

标签: javascript d3.js svg

我正在尝试找出映射是否将我的甜甜圈标签上的文本旋转180度所需的逻辑。基本上,如果它们上下颠倒,我想将它们旋转180度,以提高可读性。理想情况下,这仅适用于上下颠倒的文本标签,而不适用于已经可读的文本标签。然后,问题就变成了如何量化print (c) 0 pink 1 white 2 blue Name: colorName, dtype: object 逻辑的这些概念。我相信我的代码中的if会适合这里。这是一个片段。

r.startAngle
var margins = {top:20, left:50, bottom:20, right:20};

var width = 300;
                var arcSize = (6 * width / 100);
                var innerRadius = arcSize * 3;

                var data = [
                  {value: 43, marker: 90, label: "Cash", color: '#b8cce4', neg:false},
                  {value: 91, marker: 191, label: "Bonds", color: '#95b3d7', neg:false},
                  {value: 12, marker: 26, label: "Stocks", color: '#4f81b9', neg:false},
                  {value: 7, marker: 15, label: "Securities Funds", color: '#366092', neg:false},
                  {value: 62, marker: 130, label: "Other", color: '#a6a6a6', neg:false}
                ];

var svg = d3.select('body').append('svg').attr('width', width+100).attr('height', width+100);

var graphGroup = svg.append("g")
    .attr("transform", "translate(" + margins.left + "," + margins.top + ")");
/*
    graphGroup.append('image')
        .attr('x',width/2-50)
        .attr('y',width/2-50)
        .attr('width',100)
        .attr('height',100)
        .attr("xlink:href", 'china-life.png');
*/

graphGroup.append('text')
    .attr('x',width/2-41)
    .attr('y',width/2+14)
    .style('font-size','42px')
    .text('5%');

var arcs = data.map(function (obj, i) {
    return d3.svg.arc().innerRadius(i * arcSize + innerRadius).outerRadius((i + 1) * arcSize - (width / 100) + innerRadius);
});
var arcsGrey = data.map(function (obj, i) {
    return d3.svg.arc().innerRadius(i * arcSize + (innerRadius + ((arcSize / 2) - 2))).outerRadius((i + 1) * arcSize - ((arcSize / 2)) + (innerRadius));
});

var pieData = data.map(function (obj, i) {
    return [
        {value: obj.value * 0.75, arc: arcs[i], object: obj},
        {value: (100 - obj.value) * 0.75, arc: arcsGrey[i], object: obj},
        {value: 100 * 0.25, arc: arcs[i], object: obj}];
});

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

var g = graphGroup.selectAll('g').data(pieData).enter()
    .append('g')
    .attr('transform', 'translate(' + width / 2 + ',' + width / 2 + ') rotate(180)');
var gText = graphGroup.selectAll('g.textClass').data([{}]).enter()
    .append('g')
    .classed('textClass', true)
    .attr('transform', 'translate(' + width / 2 + ',' + width / 2 + ') rotate(180)');


g.selectAll('path').data(function (d) {
    return pie(d);
}).enter().append('path')
    .attr('id', function (d, i) {
        if (i == 1) {
            return "Text" + d.data.object.label
        }
    })
    .attr('d', function (d) {
        return d.data.arc(d);
    }).attr('fill', function (d, i) {
      if (d.data.object.neg==false) {
        return i == 0 ? d.data.object.color : i == 1 ? '#D3D3D3' : 'none' ;
      } else {
        return i == 0 ? 'red' : i == 1 ? '#D3D3D3' : 'none' ;
      }}).attr('class','segments');

/*
g.selectAll('.segments').attr('fill', function(d,i) {
  return d.data.object.neg==true ? 'red' : 'none';
});
*/

graphGroup.selectAll('g').each(function (d, index) {
    var el = d3.select(this);
    var path = el.selectAll('path').each(function (r, i) {
        if (i === 1) {
            var centroid = r.data.arc.centroid({
                startAngle: r.startAngle + 0.05,
                endAngle: r.startAngle + 0.001 + 0.05
            });
            var lableObj = r.data.object;
            g.append('text')
                .attr('font-size', ((5 * width) / 100))
                .attr('dominant-baseline', 'central')
                /*.attr('transform', "translate(" + centroid[0] + "," + (centroid[1] + 10) + ") rotate(" + (180 / Math.PI * r.startAngle + 7) + ")")
                 .attr('alignment-baseline', 'middle')*/
                .append("textPath")
                .attr("textLength", function (d, i) {
                    return 0;
                })
                .attr("xlink:href", "#Text" + r.data.object.label)
                .attr("startOffset", '5')
                .attr('font-weight','normal')
                .attr("dy", '-3em')
                .text(function(d) {
                  if (lableObj.neg==true) {
                    return '-'+lableObj.marker;
                  } else {
                    return lableObj.marker ;
                  }
                  });
        }
        if (i === 0) {
            var centroidText = r.data.arc.centroid({
                startAngle: r.startAngle,
                endAngle: r.startAngle
            });
            var lableObj = r.data.object;
            /*gText.append('text')
                .attr('font-size', ((5 * width) / 100))
                .text(lableObj.label)
                .attr('transform', "translate(" + (centroidText[0] - ((1.5 * width) / 100)) + "," + (centroidText[1] + ") rotate(" + (180) + ")"))
                .attr('dominant-baseline', 'central');*/
        }
    });
});

<script src="http://d3js.org/d3.v3.min.js"></script>

不幸的是,导致列表控制台错误后出现意外的“)”。

在代码段中,数字:15和26是“上下颠倒”的,应翻转。

问题

如何翻转甜甜圈图上的文本标签以提高可读性?是否有内置的方法,或者是修改我的逻辑的唯一方法(因此失败了)?

1 个答案:

答案 0 :(得分:1)

那些不是常规的文本元素。这些是<textPath>元素。

因此,旋转它们不是正确的解决方案。您要做的就是获取路径的长度...

var thisLength = this.getTotalLength();

...,然后使用startOffset将文本移动到路径的末尾,如下所示:

.attr("startOffset", function(){
    return index === 2 || index === 3 ? thisLength - 22 : 5
})

请注意以下事实:这里我只是获取第二个和第三个元素(神奇的数字,就像22用于填充)以更改其位置:在实际代码中,您必须根据基本的三角函数,对一个函数进行查找可以更改需要startOffset的元素。

这是您所做的更改的代码:

var margins = {
  top: 20,
  left: 50,
  bottom: 20,
  right: 20
};

var width = 300;
var arcSize = (6 * width / 100);
var innerRadius = arcSize * 3;

var data = [{
    value: 43,
    marker: 90,
    label: "Cash",
    color: '#b8cce4',
    neg: false
  },
  {
    value: 91,
    marker: 191,
    label: "Bonds",
    color: '#95b3d7',
    neg: false
  },
  {
    value: 12,
    marker: 26,
    label: "Stocks",
    color: '#4f81b9',
    neg: false
  },
  {
    value: 7,
    marker: 15,
    label: "Securities Funds",
    color: '#366092',
    neg: false
  },
  {
    value: 62,
    marker: 130,
    label: "Other",
    color: '#a6a6a6',
    neg: false
  }
];

var svg = d3.select('body').append('svg').attr('width', width + 100).attr('height', width + 100);

var graphGroup = svg.append("g")
  .attr("transform", "translate(" + margins.left + "," + margins.top + ")");
/*
    graphGroup.append('image')
        .attr('x',width/2-50)
        .attr('y',width/2-50)
        .attr('width',100)
        .attr('height',100)
        .attr("xlink:href", 'china-life.png');
*/

graphGroup.append('text')
  .attr('x', width / 2 - 41)
  .attr('y', width / 2 + 14)
  .style('font-size', '42px')
  .text('5%');

var arcs = data.map(function(obj, i) {
  return d3.svg.arc().innerRadius(i * arcSize + innerRadius).outerRadius((i + 1) * arcSize - (width / 100) + innerRadius);
});
var arcsGrey = data.map(function(obj, i) {
  return d3.svg.arc().innerRadius(i * arcSize + (innerRadius + ((arcSize / 2) - 2))).outerRadius((i + 1) * arcSize - ((arcSize / 2)) + (innerRadius));
});

var pieData = data.map(function(obj, i) {
  return [{
      value: obj.value * 0.75,
      arc: arcs[i],
      object: obj
    },
    {
      value: (100 - obj.value) * 0.75,
      arc: arcsGrey[i],
      object: obj
    },
    {
      value: 100 * 0.25,
      arc: arcs[i],
      object: obj
    }
  ];
});

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

var g = graphGroup.selectAll('g').data(pieData).enter()
  .append('g')
  .attr('transform', 'translate(' + width / 2 + ',' + width / 2 + ') rotate(180)');
var gText = graphGroup.selectAll('g.textClass').data([{}]).enter()
  .append('g')
  .classed('textClass', true)
  .attr('transform', 'translate(' + width / 2 + ',' + width / 2 + ') rotate(180)');


g.selectAll('path').data(function(d) {
    return pie(d);
  }).enter().append('path')
  .attr('id', function(d, i) {
    if (i == 1) {
      return "Text" + d.data.object.label
    }
  })
  .attr('d', function(d) {
    return d.data.arc(d);
  }).attr('fill', function(d, i) {
    if (d.data.object.neg == false) {
      return i == 0 ? d.data.object.color : i == 1 ? '#D3D3D3' : 'none';
    } else {
      return i == 0 ? 'red' : i == 1 ? '#D3D3D3' : 'none';
    }
  }).attr('class', 'segments');

/*
g.selectAll('.segments').attr('fill', function(d,i) {
  return d.data.object.neg==true ? 'red' : 'none';
});
*/

graphGroup.selectAll('g').each(function(d, index) {
  var el = d3.select(this);
  var path = el.selectAll('path').each(function(r, i) {
    if (i === 1) {
      var centroid = r.data.arc.centroid({
        startAngle: r.startAngle + 0.05,
        endAngle: r.startAngle + 0.001 + 0.05
      });
      var lableObj = r.data.object;
      var thisLength = this.getTotalLength();
      g.append('text')
        .attr('font-size', ((5 * width) / 100))
        .attr('dominant-baseline', 'central')
        /*.attr('transform', "translate(" + centroid[0] + "," + (centroid[1] + 10) + ") rotate(" + (180 / Math.PI * r.startAngle + 7) + ")")
         .attr('alignment-baseline', 'middle')*/
        .append("textPath")
        .attr("textLength", function(d, i) {
          return 0;
        })
        .attr("xlink:href", "#Text" + r.data.object.label)
        .attr("startOffset", function() {
          return index === 2 || index === 3 ? thisLength - 22 : 5
        })
        .attr('font-weight', 'normal')
        .attr("dy", '-3em')
        .text(function(d) {
          if (lableObj.neg == true) {
            return '-' + lableObj.marker;
          } else {
            return lableObj.marker;
          }
        });
    }
    if (i === 0) {
      var centroidText = r.data.arc.centroid({
        startAngle: r.startAngle,
        endAngle: r.startAngle
      });
      var lableObj = r.data.object;
      /*gText.append('text')
          .attr('font-size', ((5 * width) / 100))
          .text(lableObj.label)
          .attr('transform', "translate(" + (centroidText[0] - ((1.5 * width) / 100)) + "," + (centroidText[1] + ") rotate(" + (180) + ")"))
          .attr('dominant-baseline', 'central');*/
    }
  });
});
<script src="http://d3js.org/d3.v3.min.js"></script>