我有一个奇怪的行为,一个简单的饼图嵌套在Angular(v1)应用程序中。
d3Service.then(function(d3){ // angular service wrapper for d3
var pieVm = scope.pie;
var radius = pieVm.d3.baseWidth/2;
pieVm.d3.chart = d3.select('#container')
.append('svg')
.attr('preserveAspectRatio', 'xMinYMin meet')
.attr('viewBox', '0 0 '+pieVm.d3.baseWidth+' '+pieVm.d3.baseHeight);
// set container to the middle
pieVm.d3.container = pieVm.d3.chart.append('g')
.attr('width', pieVm.d3.baseWidth)
.attr('height', pieVm.d3.baseHeight)
.attr("transform", "translate(" + radius + ", " + radius + ")");
pieVm.d3.outerArc = d3.arc()
.innerRadius(35)
.outerRadius(50 - pieVm.d3.space)
.padAngle(pieVm.d3.space * Math.PI / 180);
pieVm.d3.arcs = d3.pie()
.value(function(d) {return d.value;})
.startAngle(pieVm.d3.startAngle - pieVm.d3.space * Math.PI / 180)
.endAngle(pieVm.d3.endAngle + pieVm.d3.space * Math.PI / 180);
});
加载数据后(与REST服务异步),称为render方法
function _loadData() {
dataService.loadData(pieVm.someArg).then(function (response) {
pieVm.data = response;
// a timeout seems to helpl a bit?
$timeout(_doReRender);
return response;
});
}
function _doReRender() {
d3Service.then(function (d3) {
var paths = pieVm.d3.container.selectAll('path')
.data(pieVm.d3.arcs(pieVm.data.entries), function(d, i){ console.log(d.index, i); return d.data.id; });
paths.enter()
.append('path')
.attr('fill', '#009898')
.each(function(d){
this._current = d;
})
.attr('d', pieVm.d3.outerArc)
.merge(paths)
.transition()
.duration(750)
.attrTween('d', arcTween)
paths.exit().remove();
});
}
如您所见,我在d.index
来电的关键功能中记录了i
和.data
。切换数据时我实际看到的内容如下:
0 1
1 0
2 2
3 3
再次切换数据后
0 0
1 1
2 2
不知何故,计算出的索引d.index
和实际索引i
随机不匹配。实际问题似乎是那些混合(有时是切换,有时不切换)。当两个数据加载(1 0
和0 1
或0 0
和1 1
)之间的订单保持不变时,转换仅按预期显示。如果它们不相同,则路径0和1将切换不是所需行为的位置。此外,这个行为是完全随机的。在没有重新加载页面的情况下,我可以在数据集之间切换10次,并且它看起来像预期的大约3或4倍,并且是第一个元素切换位置的6或7倍。
任何想法,实际发生了什么?
/编辑 为了测试我添加了一些简单的数据集(相同的行为):
var sets = [
[{id: "v01", value: 14}, {id: "v02", value: 10}, {id: "v03", value: 12}],
[{id: "v01", value: 7}, {id: "v02", value: 20}, {id: "v03", value: 7}],
[{id: "v01", value: 15}, {id: "v02", value: 18}]
];
var i = 0;
$interval(function(){
pieVm.data.entries = sets[i%sets.length];
$timeout(_doReRender);
i++;
}, 2500);