d3.js 向饼图添加元素
d3.js Adding elements to pie chart
我正在尝试使用可以显示更多或更少元素的新数据和新值来更新饼图。删除弧并更新值(具有相同数量的元素)是可以的。
问题是在添加新弧时:饼图会过渡,但它会在新弧应该出现的地方留下空白,并在饼外绘制一些弧。
下面是我如何创建饼图(忽略 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 您可以找到可用的应用程序。点击任意区显示饼状图。
我已经找到解决办法了!
我错过了为饼图中出现的新弧线定位中心的变换。我也没有选择合适的元素。例如:selectAll('.labelText') 是错误的。你最好让 selectAll('text') 输入新数据。
感谢您的所有回答!
我正在尝试使用可以显示更多或更少元素的新数据和新值来更新饼图。删除弧并更新值(具有相同数量的元素)是可以的。
问题是在添加新弧时:饼图会过渡,但它会在新弧应该出现的地方留下空白,并在饼外绘制一些弧。
下面是我如何创建饼图(忽略 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 您可以找到可用的应用程序。点击任意区显示饼状图。
我已经找到解决办法了!
我错过了为饼图中出现的新弧线定位中心的变换。我也没有选择合适的元素。例如:selectAll('.labelText') 是错误的。你最好让 selectAll('text') 输入新数据。
感谢您的所有回答!