【发布时间】:2016-09-02 08:33:31
【问题描述】:
我正在尝试使用可以显示更多或更少元素的新数据和新值来更新饼图。删除弧和更新值(具有相同数量的元素)是可以的。
问题在于添加新弧线时:饼图会过渡,但它会在新弧线的位置留下空白,并在饼图外绘制一些弧线。
这是我如何创建饼图(省略 arcTween 函数、鼠标悬停、点击等)
svg.attr('width', width).attr('height', height);
let pie = d3.layout.pie()
.value( function(d) { return d; })
.sort(null);
let arc = d3.svg.arc()
.innerRadius(innRadius)
.outerRadius(outRadius);
svg.append('g')
.attr('class', 'donut-chart')
.attr('transform', 'translate(' + (width / 2) + ',' + (height / 1.75) +')');
svg.select('.donut-chart')
.selectAll('.donut-arc')
.data(pie(values))
.enter()
.append('g')
.attr('class', 'donut-arc _selected_');
svg.selectAll('.donut-arc')
.append('path')
.attr('fill', function(d, i) {
if ( scale === 'linear') return color(d.value);
return color(labels[i]);
})
.attr('d', arc)
.each(function(d) { this._current = d; });
svg.selectAll('.donut-arc')
.append('text')
.attr('class', 'labelText')
.attr("x", function(d) {
var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2;
d.cx = Math.cos(a) * (outRadius + 75);
return d.x = Math.cos(a) * (outRadius + 30);
})
.attr("y", function(d) {
var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2;
d.cy = Math.sin(a) * (outRadius + 75);
return d.y = Math.sin(a) * (outRadius + 20);
})
.text(function(d, i) {
return labels[i];
})
.style("text-anchor", function(d) {
var rads = ((d.endAngle - d.startAngle) / 2) + d.startAngle + 10;
if ( (rads > 7 * Math.PI / 4 && rads < Math.PI / 4) || (rads > 3 * Math.PI / 4 && rads < 5 * Math.PI / 4) ) {
return "middle";
} else if (rads >= Math.PI / 4 && rads <= 3 * Math.PI / 4) {
return "start";
} else if (rads >= 5 * Math.PI / 4 && rads <= 7 * Math.PI / 4) {
return "end";
} else {
return "middle";
}
});
svg.selectAll('path').transition().attrTween("d", arcTween);
这就是我更新馅饼的方式:
let paths = svg.datum(values).selectAll('path').data(pie);
let textLabels = svg.selectAll('.labelText').data(pie(values));
paths.enter()
.append('path')
.attr('fill', function(d, i) {
if ( scale === 'linear') return color(d.value);
return color(labels[i]);
})
.attr('d', arc)
.each(function(d) { this._current = d; });
textLabels.enter()
.append('text');
paths.transition()
.duration(1000)
.attrTween('d', arcTween);
textLabels.transition()
.duration(1250)
.attr("x", function(d) {
var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2;
d.cx = Math.cos(a) * (outRadius + 75);
return d.x = Math.cos(a) * (outRadius + 30);
})
.attr("y", function(d) {
var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2;
d.cy = Math.sin(a) * (outRadius + 75);
return d.y = Math.sin(a) * (outRadius + 20);
})
.style("text-anchor", function(d) {
var rads = ((d.endAngle - d.startAngle) / 2) + d.startAngle + 10;
if ( (rads > 7 * Math.PI / 4 && rads < Math.PI / 4) || (rads > 3 * Math.PI / 4 && rads < 5 * Math.PI / 4) ) {
return "middle";
} else if (rads >= Math.PI / 4 && rads <= 3 * Math.PI / 4) {
return "start";
} else if (rads >= 5 * Math.PI / 4 && rads <= 7 * Math.PI / 4) {
return "end";
} else {
return "middle";
}
})
.text(function(d, i) {
return labels[i];
});
paths.exit().remove();
textLabels.exit().remove();
svg.transition().attr({width: width, height: height});
我做错了什么?
这个饼图是一个 Ember 组件,它的完整代码可以在here找到它的完整代码
here 你可以找到工作的应用程序。点击任一区即可显示饼图。
【问题讨论】:
-
你会得到更好的答案,如果你能把它放在一个工作小提琴上。
-
对不起,从来没有做过小提琴。我已经链接了应用程序 URL,以便您可以看到它正在运行。
-
您可能不需要单独的代码来创建和更新饼图。您的代码实际上是相同的,我认为您可以将其重写为一个接收数据并绘制或更新饼图的函数。使用进入、更新和退出选择来控制新元素和更新元素的不同行为。 bost.ocks.org/mike/join 如果你这样做,你的问题可能会消失,或者至少会更容易解决。
标签: javascript d3.js ember.js charts pie-chart