我在我的应用程序中使用d3作为条形图,并且需要使用一段文本为条形图所代表的数据值注释每个条形。
到目前为止我的工作原理如下:
layers = svg.selectAll('g.layer')
.data(stacked, function(d) {
return d.dataPointLegend;
})
.enter()
.append('g')
.attr('class', function(d) {
return d.dataPointLegend;
});
layers.selectAll('rect')
.data(function(d) {
return d.dataPointValues;
})
.enter()
.append('rect')
.attr('x', function(d) {
return x(d.pointKey);
})
.attr('width', x.rangeBand())
.attr('y', function(d) {
return y(d.y0 + d.pointValue);
})
.attr('height', function(d) {
return height - margin.bottom - margin.top - y(d.pointValue)
});
layers.selectAll('text')
.data(function(d) {
return d.dataPointValues;
})
.enter()
.append('text')
.text(function() {
return 'bla';
})
.attr('x', function(d) {
return x(d.pointKey) + x.rangeBand() / 2;
})
.attr('y', function(d) {
return y(d.y0 + d.pointValue) - 5;
})
如果数据中存在某个属性,我实际上只想附加一个文本元素。
我在文档中看到了datum
选择方法,并想知道这是否是我需要的,如果我正在寻找的属性不存在,我不确定如何取消追加调用。
由于
尝试2
好的所以我又进行了另一次尝试,这次使用each
函数,如下所示:
layers.selectAll('text')
.data(function(d) {
return d.dataPointValues;
})
.enter()
//This line needs to be my each function I think?
.append('text')
.each(function(d){
if(d.pointLabel) {
d3.select(this)
.text(function(d) {
return d.pointLabel;
})
.attr('x', function(d) {
return x(d.pointKey) + x.rangeBand() / 2;
})
.attr('y', function(d) {
return y(d.y0 + d.pointValue) - 5;
})
.attr('class', 'data-value')
}
});
}
我现在遇到的问题是,无论是否存在pointLabel
属性,我都会添加一个文本元素。
感觉我已经接近了,我确实想知道我是否应该将append('text')
向下移动到每个中,但是当我尝试时我得到了一个错误,因为d3并不期待那个特定的电话链。 / p>
答案 0 :(得分:1)
如何使用d3的数据绑定...而不是将文本附加到layers.enter()
选项,请执行以下操作整个 layers
选择,即包括更新节点:
labels = layers.selectAll('text')
.data(function(d) {
// d is the datum of the parent, and for this example
// let's assume that the presence of `pointLabel`
// indicates whether the label should be displayed or not.
// You could work in more refined logic for it if needed:
return d.pointLabel ? [d] : [];
})
// The result of the above is that if a label is needed, a binding will
// occur to a single element array containing `d`. Otherwise, it'll bind
// to an empty array. After that binding, using enter, update and exit,
// you get to add, update or even remove text (you might need removal if
// you're updating an existing view whose existing label needs to go away)
labels.enter()
.append("text")
labels
.text(function(d) { d.pointLabel })
.attr('x', function(d) {
return x(d.pointKey) + x.rangeBand() / 2;
})
.attr('y', ...)
labels.exit()
.remove()
这里的诀窍(它不是一个技巧,但它不是一个非常常见的d3用例)是它要么绑定到单个元素数组[d]
或者是空白[]
,这就是您使用enter()
选项仅在需要时创建标签的方式。此方法优于非数据绑定应用程序的好处是,可以多次调用此代码 - 每当d.pointLabel
更改或应用程序的状态更改时 - 以及标签' presense(或缺乏存在,即删除)将相应更新。