D3.js Barchart,拆分文本

时间:2015-11-08 12:50:54

标签: javascript arrays d3.js

我有D3.js条形图,我想在其上显示数组中的数字。每个栏都有自己的数组,例如[12, 34, 65]。我能够在每个条形图的顶部只显示数组作为文本,但我想分割每个数组并从上到下显示每个数字,因此对于[12, 34, 65]条,底部为12 ,然后34位于中间,65位于顶部。这该怎么做?到目前为止,我有这样的代码,它只显示每个栏顶部的数组:

        g.selectAll("text")
           .data(dataset)
           .enter()
           .append("text")
           .text(function(d) {
                return d;
           })
           .attr("font-family", "sans-serif")
           .attr("font-size", "11px")
           .attr("fill", "white")
           .attr("text-anchor", "middle")
           .attr("x", function(d, i) {
                return ...;
           })          
           .attr("y", function(d) {
                return ...;
           });

其中dataset是一个数组数组。 d将对应[12, 34, 65]。我需要一种方法将其拆分为单个数字,并为每个数字指定y。同时x显然应该对每个栏保持不变。还希望通过改变与数字对应的每个片段的颜色,将每个条形分割成与每个数字对应的部分,或者通过绘制黑白数字或更好的数字。

2 个答案:

答案 0 :(得分:2)

好的我有一个数据集,其中我有一个数组形式的标签,你说每个栏都有自己的数字数组,比如[12, 34, 65]

{
    "letter": "B",
        "frequency": 0.03492,
    label: [10, 20, 30]//this is the array which will be displayed on bar's top middle bottom
} 

要在条形图上附加标签,请执行以下操作

var rects = svg.selectAll(".bar")
    .data(data)
    .enter().append("g");
//make the bars
rects.append("rect")
    .attr("class", "bar")
    .attr("x", function (d) {
    return x(d.letter);
})
    .attr("width", x.rangeBand())
    .attr("y", function (d) {
    return y(d.frequency);
})
    .attr("height", function (d) {
    return height - y(d.frequency);
});
//text @ the top
rects.append("text")
    .attr("x", function (d) {
    return x(d.letter) + x.rangeBand() / 2;
})
    .attr("y", function (d) {
    return y(d.frequency) + 10;
}).attr("font-family", "sans-serif")
    .attr("font-size", "11px")
    .attr("fill", "white")
    .attr("text-anchor", "middle")
    .attr("dy", ".35em")
    .text(function (d) {
    return d.label[0];
});
//text @ the middle
rects.append("text")
    .attr("x", function (d) {
    return x(d.letter) + x.rangeBand() / 2;
})
    .attr("y", function (d) {
    return (height + y(d.frequency))/2;
}).attr("font-family", "sans-serif")
    .attr("font-size", "11px")
    .attr("fill", "white")
    .attr("text-anchor", "middle")
    .attr("dy", ".35em")
    .text(function (d) {
    return d.label[1];
});
//text @ the bottom
rects.append("text")
    .attr("x", function (d) {
    return x(d.letter) + x.rangeBand() / 2;
})
    .attr("y", function (d) {
    return height - 10;
}).attr("font-family", "sans-serif")
    .attr("font-size", "11px")
    .attr("fill", "white")
    .attr("text-anchor", "middle")
    .attr("dy", ".35em")
    .text(function (d) {
    return d.label[2];
});

工作代码here

希望这有帮助!

答案 1 :(得分:1)

要解决您的问题,您需要处理nested data with d3,即您需要先为每个堆叠条创建一个组:

var stacks = root.selectAll("g.stack")
.data(dataset)
.enter()
.append("g").attr("class","stack")

然后,对于每个堆栈,通过使用从父数据中提取嵌套数组的新data函数,创建一个新的选择,将嵌套数组作为数据。

var bars = stacks.selectAll("g.bar")
.data(function(d, i) { return d; })
.enter().append(...)

对于堆叠中的每个条形,您可以使用不同的颜色,例如,使用d3.scale.category10

这是完整的例子:

var root = d3.selectAll("svg>g#root")
var dataset = [[10,20,50],[70,40,10],[20,40,10]]
var color = d3.scale.category10()

dataset.forEach( function(d) {
    d.sort( function(a,b)  { return b-a; } )
})

var stacks = root.selectAll("g.stack")
.data(dataset)
.enter()
.append("g").attr("class","stack")
.attr("transform", function(d,i) {
    return "translate(0,"+ (i * 30) +")"
})

var bars = stacks.selectAll("g.bar")
.data(function(d, i) { return d; })
.enter()
.append("g").attr("class","bar")

var barWidth = function(d,i) { return d * 2 }
var barColor = function(d,i) { return color(i) }

bars.append("rect")
.attr("height", "20")
.attr("x",      "0")
.attr("y",      "0")
.attr("width",  barWidth )
.style("fill",  barColor )

bars.append("text")
.text( function(d) { return d } )
.attr("x", barWidth )
.attr("y", 9)
.attr("transform", "translate(-10,0)" )
svg { border: solid 1px gray }

svg text {
    font-family: sans-serif;
    font-size:   11px;
    fill:        white;
    text-anchor: middle;
}

svg rect {
    fill:   gray;
    stroke: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width=200 height=100 id="container" 
     style="border: solid 1px gray">
    <g id="root" transform="translate(10,10)"></g>
</svg>

请注意,为简洁起见,该示例不使用任何d3.scale将数据空间转换为几何空间。有关详细信息,请参阅d3 wiki

该示例当前假设数组中的值是绝对值,即所有条形均以x="0"开始。如果您需要实际堆叠相对值,我建议首先为每个条形预先计算x的相应值,方法是将已排序的嵌套数组的先前值相加:

var sum = function(a,b) { return a+b }
var derivedData = dataset.map( function(d,i) {
    d.sort( function(a,b)  { return b-a; } )
    return d.map( function(v,i) {
        // `value` determines the width or height of a bar
        // `sum`   determines the position of the bar
        return { value: v, sum: d.slice(0,i+1).reduce(sum) }
    })
})