我创建了一个水平图例,显示在我用d3.js创建的条形图上方。
这是我的第一次尝试,我努力想象如何定位图例中的每个项目以考虑上一个项目的宽度。
所以这就是我到目前为止所看到的:
这是我的代码与图例呈现相关:
var legendRectSize = 18,
legendSpacing = 4;
svg.selectAll('.legend')
.data(data.chartKeys)
.enter()
.append('g')
.attr('class', 'legend')
.attr('transform', function(d, i) {
//width = the chart area width
var horz = width/2 + i*100; //This needs to add previously rendered elements width instead
return 'translate(' + horz + ',' + 0 + ')';
});
svg.selectAll('.legend').append('rect')
.attr('width', legendRectSize)
.attr('height', legendRectSize)
.attr('class', function(d) {
return d;
})
.style('stroke', 'black');
svg.selectAll('.legend').append('text')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.text(function(d) {
return d;
});
正如你在转换函数中看到的那样,我只是将每个项目的索引乘以因子100来水平展开它们,但实际上我可以确定先前渲染元素的宽度(所以彩色框和文本组合)并添加它,使它们之间的间距是均匀的,没有任何重叠。
转换函数中有没有办法获取上一个项目,或者最好采用不同的方法?
由于
答案 0 :(得分:3)
如果需要内联块样式布局,则需要根据实际文本宽度保留某种运行偏移量。您可以在此处查看示例:http://jsfiddle.net/nrabinowitz/r7yodrm1/
关键部分是将offset
保留在外部范围内,然后使用.each
更新带有文本宽度的偏移量:
var offset = 0;
var legendBlockWidth = 15;
var textMargin = 3;
legend.enter().append('g')
.attr('class', 'legend')
.each(function(key, i) {
var item = d3.select(this);
var text = item.append('text')
.text(key);
// ... snip ...
// Translate the group based on the running width
item.attr('transform', function() {
return 'translate(' + offset + ',0)';
});
// Update the offset
offset += text.node().getBBox().width + legendBlockWidth + textMargin * 3;
});
您可以使用此变体来代替最大文字宽度,这样可以提供均匀的间距而不会发生碰撞:http://jsfiddle.net/nrabinowitz/r7yodrm1/2/
var maxOffset = 0;
legend2.enter().append('g')
.attr('class', 'legend2')
.each(function(key, i) {
var item = d3.select(this);
var text = item.append('text')
.text(key);
// ... snip ...
// Update the offset
maxOffset = Math.max(
maxOffset,
text.node().getBBox().width + legendBlockWidth + textMargin * 3
);
});
legend2.attr('transform', function(d, i) {
return 'translate(' + (maxOffset * i) +',50)';
});