【问题标题】:D3 - Placing labels and lines on a half pie/half donut chartD3 - 在半饼图/半圆环图上放置标签和线条
【发布时间】:2017-03-21 20:27:34
【问题描述】:

我是这个主题的新手,我正在尝试使用 D3.js v4 构建一个简单的半饼图/半甜甜圈图。结果应该类似于以下示例中的图表:http://bl.ocks.org/dbuezas/9306799

我的问题是标签和线条的位置。

这是我当前的代码:

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="http://d3js.org/d3.v4.min.js"></script>
<script>

var data = [
    {name: "ABC", val: 11975},
    {name: "DEF", val: 5871},
    {name: "GEH", val: 8916}
];

var margin = {
    top: 40,
    right: 40,
    bottom: 40,
    left: 40
};

var width = 800 - margin.right - margin.left;
var height = 400 - margin.top - margin.bottom;
var radius = 300;

var svg = d3.select('body')
    .append('svg')
    .attr('width', width)
    .attr('height', height)
    .append('g')
    .attr('transform', 'translate(' + width / 2 + ',' + height + ')');

svg.append('g')
    .attr('class', 'slices');
svg.append('g')
    .attr('class', 'labels');
svg.append('g')
    .attr('class', 'lines');

var color = d3.scaleOrdinal(d3.schemeCategory20);

var pie = d3.pie()
    .sort(null)
    .value(function (d) {
        return d.val;
    })
    .startAngle(-90 * (Math.PI / 180))
    .endAngle(90 * (Math.PI / 180));

// donut chart arc
var arc = d3.arc()
    .innerRadius(radius - 100)
    .outerRadius(radius - 50);

var slice = svg.select('.slices')
    .selectAll('path.slice')
    .data(pie(data));

slice.enter()
    .append('path')
    .attr('d', arc)
    .attr('fill', function (d) {
        return color(d.data.name);
    })
    .attr('class', 'slice');

var sliceDots = svg.select('.slices')
    .selectAll('circle')
    .data(pie(data));

sliceDots.enter()
    .append('circle')
    .attr('class', 'dot')
    .attr('cx', function (d) {
        return arc.centroid(d)[0];
    })
    .attr('cy', function (d) {
        return arc.centroid(d)[1];
    })
    .attr('r', 2)
    .attr('fill', 'black');

// label arc
var labelArc = d3.arc()
    .innerRadius(radius * 0.9)
    .outerRadius(radius * 0.9);

var labels = svg.select('.labels')
    .selectAll('text')
    .data(pie(data));

labels.enter()
    .append('text')
    .attr('dy', '.35em')
    .attr('text-anchor', 'middle')
    .attr('class', 'labels')
    .text(function (d) {
        return d.data.name;
    })
    .attr('transform', function (d) {
        return 'translate(' + labelArc.centroid(d)[0] + ',' + labelArc.centroid(d)[1] + ')';
    });

// lines
var polyline = svg.select('.lines')
    .selectAll('polyline')
    .data(pie(data));

polyline.enter()
    .append('polyline')
    .attr('stroke-width', '2px')
    .attr('stroke', 'black')
    .attr('opacity', '0.4')
    .attr('points', function (d) {
        return [arc.centroid(d), labelArc.centroid(d)];
    });
 </script>
 </body>

有没有简单的解决方案?

【问题讨论】:

  • 我认为您应该更改 transform 属性以显示标签。
  • 你想把标签放在哪里?在路径之上还是路径之外?另外,你想让它们旋转吗?
  • 我正在尝试将标签放置在路径上,标签不应旋转。也许使用第二个半径更大的弧形对象更容易。

标签: javascript d3.js svg charts


【解决方案1】:

我相信使用质心是一种很好的方法,所以我只是添加了 getTextWidth(来自这里:Calculate text width with JavaScript)方法来确定值标签的长度,然后将其移动到左侧。

.attr("transform", function (d) {
    var textWidth = getTextWidth(d.data.val.toString(), "Arial");
    return "translate(" + (arc.centroid(d)[0] - textWidth) + "," + arc.centroid(d)[1] + ")"; 
})

这是一个 JSFiddle:https://jsfiddle.net/w6d4hcb9/2/

【讨论】:

  • 谢谢,但我想要甜甜圈外面的标签。我更改了以前的解决方案并为标签添加了第二条弧线。您始终将位置移动到左侧,但我认为它必须取决于角度:标签从左到左,从右到右。这是我当前版本的 JSFiddle:jsfiddle.net/Lnj00so0
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-27
  • 1970-01-01
  • 1970-01-01
  • 2021-10-09
  • 1970-01-01
相关资源
最近更新 更多