在条形图中的条形顶部显示值
Posted
技术标签:
【中文标题】在条形图中的条形顶部显示值【英文标题】:Show values on top of bars in a barChart 【发布时间】:2014-09-21 10:57:39 【问题描述】:我有一个带有 x 轴序数刻度的条形图。我想在每个条的顶部或每个条的底部显示 y 值。当鼠标悬停在条上时显示 y 值也是可以接受的。 dc.js 中是否有功能或方法可以做到这一点?这是jsfiddle,我的代码在图片下方>
编辑:这是我的代码: HTML
<body>
<div id='Chart'>
</div>
</body>
JS
var data = [
Category: "A",
ID: "1"
,
Category: "A",
ID: "1"
,
Category: "A",
ID: "1"
,
Category: "A",
ID: "2"
,
Category: "A",
ID: "2"
,
Category: "B",
ID: "1"
,
Category: "B",
ID: "1"
,
Category: "B",
ID: "1"
,
Category: "B",
ID: "2"
,
Category: "B",
ID: "3"
,
Category: "B",
ID: "3"
,
Category: "B",
ID: "3"
,
Category: "B",
ID: "4"
,
Category: "C",
ID: "1"
,
Category: "C",
ID: "2"
,
Category: "C",
ID: "3"
,
Category: "C",
ID: "4"
,
Category: "C",
ID: "4"
,
Category: "C",
ID: "5"
];
var ndx = crossfilter(data);
var XDimension = ndx.dimension(function (d)
return d.Category;
);
var YDimension = XDimension.group().reduceCount(function (d)
return d.value;
);
dc.barChart("#Chart")
.width(480).height(300)
.dimension(XDimension)
.group(YDimension)
.transitionDuration(500)
.xUnits(dc.units.ordinal)
.label(function(d) return d.value)
.x(d3.scale.ordinal().domain(XDimension))
dc.renderAll();
【问题讨论】:
您能发布您的代码和/或JSFiddle 之类的吗? @mdml 完成!如果您还需要什么,请告诉我。 获取 FIREBASE 警告:/UniqueActivities 的 on() 或 once() 失败:错误:permission_denied:客户端无权访问所需数据。 @elzi 我创建了一个jsfiddle 并简化了代码。 【参考方案1】:检查更新jsfiddle
.renderlet(function(chart)
var barsData = [];
var bars = chart.selectAll('.bar').each(function(d) barsData.push(d); );
//Remove old values (if found)
d3.select(bars[0][0].parentNode).select('#inline-labels').remove();
//Create group for labels
var gLabels = d3.select(bars[0][0].parentNode).append('g').attr('id','inline-labels');
for (var i = bars[0].length - 1; i >= 0; i--)
var b = bars[0][i];
//Only create label if bar height is tall enough
if (+b.getAttribute('height') < 18) continue;
gLabels
.append("text")
.text(barsData[i].data.value)
.attr('x', +b.getAttribute('x') + (b.getAttribute('width')/2) )
.attr('y', +b.getAttribute('y') + 15)
.attr('text-anchor', 'middle')
.attr('fill', 'white');
)
如果您不希望在重绘条形图时显示标签(例如,当用户过滤/单击其他图表后条形图发生变化时),您可以将旧值的检查从 de renderlet 移动到 preRedraw 听众。
.on("preRedraw", function(chart)
//Remove old values (if found)
chart.select('#inline-labels').remove();
)
另类
D3-ish 方式
演示jsfiddle
.renderlet(function (chart)
//Check if labels exist
var gLabels = chart.select(".labels");
if (gLabels.empty())
gLabels = chart.select(".chart-body").append('g').classed('labels', true);
var gLabelsData = gLabels.selectAll("text").data(chart.selectAll(".bar")[0]);
gLabelsData.exit().remove(); //Remove unused elements
gLabelsData.enter().append("text") //Add new elements
gLabelsData
.attr('text-anchor', 'middle')
.attr('fill', 'white')
.text(function(d)
return d3.select(d).data()[0].data.value
)
.attr('x', function(d)
return +d.getAttribute('x') + (d.getAttribute('width')/2);
)
.attr('y', function(d) return +d.getAttribute('y') + 15; )
.attr('style', function(d)
if (+d.getAttribute('height') < 18) return "display:none";
);
)
【讨论】:
你太棒了。非常感谢。 这很棒。它还不是非常惯用的 d3 代码,因为通常您使用选择来进行循环,并且更少的手动索引,但它越来越接近了。谢谢! @Gordon 我用更惯用代码的替代方法更新了我的答案 使用 dc 2.0,.on('pretransition', function ...)
优于 .renderlet(function ...)
@dimirc - 感谢这个惊人的答案。我已经使用了很多,但我正在尝试将此解决方案用于堆叠条形图。我在这里发布了一个关于此的问题:***.com/questions/39581885/…【参考方案2】:
在 dc.js 版本 3.* 中。您可以使用.renderLabel(true)
。它将在顶部打印值
【讨论】:
【参考方案3】:这里有一个使用 renderlet
方法的 hacky 解决方案。 jsFiddle:http://jsfiddle.net/tpsc5f9f/4/
JS
var barChart = dc.barChart("#Chart")
.width(480).height(300)
.dimension(XDimension)
.group(YDimension)
.transitionDuration(500)
.xUnits(dc.units.ordinal)
.x(d3.scale.ordinal().domain(XDimension))
dc.renderAll();
barChart.renderlet(function(chart)
moveGroupNames();
);
function moveGroupNames()
var $chart = $('#Chart'),
bar = $chart.find('.bar');
bar.each(function (i, item)
var bar_top = this.height.baseVal.value;
var bar_left = this.width.baseVal.value;
var bar_offset_x = 30;
var bar_offset_y = 33;
var bar_val = $(this).find('title').html().split(':')[1];
$chart.append('<div class="val" style="bottom:'+(bar_top+bar_offset_y)+'px;left:'+((bar_left*i)+(bar_offset_x))+'px;width:'+bar_left+'px">'+bar_val+'</div>');
);
添加了 CSS
body
margin-top:20px;
#Chart
position:relative;
#Chart .val
position:absolute;
left:0;
bottom:0;
text-align: center;
【讨论】:
太棒了。但是,我正在寻找在每个栏的顶部显示数字,而不是栏名称。很抱歉造成混淆。我实际上用 renderlet 实现了相同的结果,但不知道如何在每个条形图的顶部显示数字(y 值)。 好吧,在这种情况下,这是一个非常老套的解决方案,哈哈:jsfiddle.net/tpsc5f9f/4 哎呀哎呀。我很生气它不是 dc.js 的默认功能。 提交公关!不过,我认为您应该能够直接从栏中获取数据。 d3 用其数据注释每个 dom 元素。 @elzi,是否愿意在上面编辑您的答案,至少使用标题 hack? 谢谢。请注意,d3.each
提供的 d
参数提供了数据,因此不需要标题 hack。您的解决方案非常有创意,但它所做的工作超出了它的需要。【参考方案4】:
如果您对图表使用专门的 valueAccessor,您可以在 dimirc 的“D3-ish way”解决方案中进行以下替换。
改变
.text(function(d)
return d3.select(d).data()[0].data.value
)
到
.text(function(d)
return chart.valueAccessor()(d3.select(d).data()[0].data)
);
【讨论】:
【参考方案5】:此函数会将行图的标签重新定位到每行的末尾。类似的技术可以用于使用“y”属性的条形图。
标签与行矩形一起动画,使用图表的 transitionDuration 使用图表的 valueAccessor 函数 使用图表的 xAxis 比例计算标签位置rowChart.on('pretransition', function(chart)
var padding = 2;
chart.selectAll('g.row > text') //find all row labels
.attr('x', padding) //move labels to starting position
.transition() //start transition
.duration(chart.transitionDuration()) //use chart's transitionDuration so labels animate with rows
.attr('x', function(d) //set label final position
var dataValue = chart.valueAccessor()(d); //use chart's value accessor as basis for row label position
var scaledValue = chart.xAxis().scale()(dataValue); //convert numeric value to row width
return scaledValue+padding; //return scaled value to set label position
);
);
【讨论】:
以上是关于在条形图中的条形顶部显示值的主要内容,如果未能解决你的问题,请参考以下文章