我的要求是使用纯d3绘制一个类别分组的条形图,其中每个类别具有不同数量的组。我不知道如何使用域和范围来满足我的要求。
我试着按照d3 nested grouped bar chart的答案给出的方式,但在我的情况下它不起作用。
这里我的图形结构如下:
答案 0 :(得分:0)
您提到的答案的问题在于,它只适用于具有相同子项的值。为了处理动态子值,我采用了这种方法
让我们为我们的团队创建颜色映射:
var color = {
Mechanical: '#4A7B9D',
Electrical: '#54577C',
Hydraulic: '#ED6A5A'
};
我们还需要一个具有嵌套值的结构,它们将是内部组:
// Simulated data structure
var data = [{
key: 'Mechanical',
values: [{
key: 'Gear',
value: 11
}, {
key: 'Bearing',
value: 8
}, {
key: 'Motor',
value: 3
}]
}];
我创建了一个barPadding
值,它将决定条之间的分隔:
var barPadding = 120;
我们需要一个虚拟scale
来获取条形的rangeBand
,让我们这样做:
// dummy array
var rangeBands = [];
// cummulative value to position our bars
var cummulative = 0;
data.forEach(function(val, i) {
val.cummulative = cummulative;
cummulative += val.values.length;
val.values.forEach(function(values) {
rangeBands.push(i);
})
});
// set scale to cover whole svg
var x_category = d3.scale.linear()
.range([0, width]);
// create dummy scale to get rangeBands (width/childrenValues)
var x_defect = d3.scale.ordinal().domain(rangeBands)
.rangeRoundBands([0, width], .1);
var x_category_domain = x_defect.rangeBand() * rangeBands.length;
x_category.domain([0, x_category_domain]);
然后让我们添加所有类别组g元素:
var category_g = svg.selectAll(".category")
.data(data)
.enter().append("g")
.attr("class", function(d) {
return 'category category-' + d.key;
})
.attr("transform", function(d) { // offset by inner group size
var x_group = x_category((d.cummulative * x_defect.rangeBand()));
return "translate(" + x_group + ",0)";
})
.attr("fill", function(d) { // make child elements of group "inherit" this fill
return color[d.key];
});
添加内部组g元素:
var defect_g = category_g.selectAll(".defect")
.data(function(d) {
return d.values;
})
.enter().append("g")
.attr("class", function(d) {
return 'defect defect-' + d.key;
})
.attr("transform", function(d, i) { // offset by index
return "translate(" + x_category((i * x_defect.rangeBand())) + ",0)";
});
让我们的g元素添加标签:
var category_label = category_g.selectAll(".category-label")
.data(function(d) {
return [d];
})
.enter().append("text")
.attr("class", function(d) {
console.log(d)
return 'category-label category-label-' + d.key;
})
.attr("transform", function(d) {
var x_label = x_category((d.values.length * x_defect.rangeBand() + barPadding) / 2);
var y_label = height + 30;
return "translate(" + x_label + "," + y_label + ")";
})
.text(function(d) {
return d.key;
})
.attr('text-anchor', 'middle');
var defect_label = defect_g.selectAll(".defect-label")
.data(function(d) {
return [d];
})
.enter().append("text")
.attr("class", function(d) {
console.log(d)
return 'defect-label defect-label-' + d.key;
})
.attr("transform", function(d) {
var x_label = x_category((x_defect.rangeBand() + barPadding) / 2);
var y_label = height + 10;
return "translate(" + x_label + "," + y_label + ")";
})
.text(function(d) {
return d.key;
})
.attr('text-anchor', 'middle');
最后我们的意见:
var rects = defect_g.selectAll('.rect')
.data(function(d) {
return [d];
})
.enter().append("rect")
.attr("class", "rect")
.attr("width", x_category(x_defect.rangeBand() - barPadding))
.attr("x", function(d) {
return x_category(barPadding);
})
.attr("y", function(d) {
return y(d.value);
})
.attr("height", function(d) {
return height - y(d.value);
});
以下是plnkr中的上述代码:https://plnkr.co/edit/L0eQwtEMQ413CpoS5nvo?p=preview