我有一个条形图,我使用过渡来设置矩形元素的高度,如下所示:
//Create a layer for each category of data that exists, as per dataPointLegend values
//e.g. DOM will render <g class="successful"><g>
layers = svg.selectAll('g.layer')
.data(stacked, function(d) {
return d.dataPointLegend;
})
.enter()
.append('g')
.attr('class', function(d) {
return d.dataPointLegend;
})
//transform below is used to shift the entire layer up by one pixel to allow
//x-axis to appear clearly, otherwise bars inside layer appear over the top.
.attr('transform', 'translate(0,-1)');
//Create a layer for each datapoint object
//DOM will render <g class="successful"><g></g><g>
barLayers = layers.selectAll('g.layer')
.data(function(d) {
return d.dataPointValues;
})
.enter()
.append('g');
//Create rect elements inside each of our data point layers
//DOM will render <g class="successful"><g><rect></rect></g></g>
barLayers
.append('rect')
.attr('x', function(d) {
return x(d.pointKey);
})
.attr('width', x.rangeBand())
.attr('y', height - margin.bottom - margin.top)
.attr('height', 0)
.transition()
.delay(function(d, i) {
return i * transitionDelayMs;
})
.duration(transitionDurationMs)
.attr('y', function(d) {
return y(d.y0 + d.pointValue);
})
.attr('height', function(d) {
return height - margin.bottom - margin.top - y(d.pointValue)
});
然后我有一个用于附加文本元素的进一步选择
//Render any point labels if present
//DOM will render <g><g><rect></rect><text></text></g></g>
if (width > miniChartWidth) {
barLayers
.append('text')
.text(function(d) {
return d.pointLabel
})
.attr('x', function(d) {
return x(d.pointKey) + x.rangeBand() / 2;
})
.attr('y', function(d) {
var textHeight = d3.select(this).node().getBoundingClientRect().height;
//Position the text so it appears below the top edge of the corresponding data bar
return y(d.y0 + d.pointValue) + textHeight;
})
.attr('class', 'data-value')
.attr('fill-opacity', 0)
.transition()
.delay(function(d, i) {
return i * transitionDelayMs + transitionDurationMs;
})
.duration(transitionDurationMs)
.attr('fill-opacity', 1);
}
在所有rects完成高度增长之后,这很好地淡化了文本元素。我想知道的是,当每个柱完成其过渡时,是否可以将文本元素附加到相应的图层?
我已经看到了这个问题的答案 - Show text only after transition is complete d3.js
这看起来与我所追求的一致,我尝试在我的矩形渲染周期中添加.each('end',...)
,如此
.each('end', function(d){
barLayers
.append('text')
.text(function() {
return d.pointLabel
})
.attr('x', function() {
return x(d.pointKey) + x.rangeBand() / 2;
})
.attr('y', function() {
var textHeight = d3.select(this).node().getBoundingClientRect().height;
//Position the text so it appears below the top edge of the corresponding data bar
return y(d.y0 + d.pointValue) + textHeight;
})
.attr('class', 'data-value')
.attr('fill-opacity', 0)
.transition()
.delay(function(d, i) {
return i * transitionDelayMs + transitionDurationMs;
})
.duration(transitionDurationMs)
.attr('fill-opacity', 1);
});
但是,对于我的每个text
,我的每个数据点只保留一个g
,我最终会得到很多rect
元素。
我觉得我很亲密,但需要你聪明人的帮助:)
由于
答案 0 :(得分:1)
whateverTheSelectionIs
.each('end', function(d){
barLayers
.append('text')
.each
分别针对您选择中的每个元素运行,并在每个元素内部向每个barLayer(barLayers)添加文本元素。所以你将得到一个(barLayers.size()* selection.size())数量的文本元素整体添加。您需要在右侧栏中添加一个文本元素/ g。
以下是可能有效的软糖。这很棘手,因为你要添加的文本是调用.each函数的选择中的reces的兄弟...,d3.select(this.parentNode)应该将你移动到rect的父级,这将是正确的barLayer。
whateverTheSelectionIs
.each('end', function(d,i){
d3.select(this.parentNode)
.append('text')