Reputation: 3479
I've a grouped bar chart based on D3
. Is there a way I can reduce the gap between bars in each group and not between the groups. I've a fixed width for each bar.
Snippet as follows:
//DATA
var data = [
{
category: "test4",
type1: 100,
type2: 200,
type3: 0,
column: "column1"
},
{
category: "test4",
type1: 0,
type2: 0,
type3: 500,
column: "column2"
},
{
category: "test3",
type1: 100,
type2: 200,
type3: 0,
column: "column1"
},
{
category: "test3",
type1: 0,
type2: 0,
type3: 500,
column: "column2"
},
{
category: "test1",
type1: 100,
type2: 200,
type3: 0,
column: "column1"
},
{
category: "test1",
type1: 0,
type2: 0,
type3: 500,
column: "column2"
},
{
category: "test2",
type1: 150,
type2: 100,
type3: 0,
column: "column1"
},
{
category: "test2",
type1: 0,
type2: 0,
type3: 400,
column: "column2"
}
];
var groupData = d3
.nest()
.key(function(d) {
return d.column + d.category;
})
.rollup(function(v) {
return {
...v[0],
total: v[0].type1 + v[0].type2 + v[0].type3
};
})
.entries(data)
.map(function(d) {
return { ...d.value };
});
//INITIAL SETUP
var margin = { top: 30, right: 10, bottom: 50, left: 40 };
var width = groupData.length * 80 - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
var barwidth = 40;
var tip = d3
.tip()
.attr("class", "d3-tip")
.html(function(d) {
return "<span>Test</span>";
});
var graph = d3
.select("#chart-area")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
graph.call(tip);
var x0 = d3
.scaleBand()
.rangeRound([0, width])
.paddingInner(0.1);
var x1 = d3.scaleBand().padding(0.05);
var y = d3.scaleLinear().range([height, 0]);
var y1 = d3.scaleBand();
var z = d3.scaleOrdinal().range(["#98abc5", "#8a89a6"]);
var stack = d3.stack();
x0.domain(
data.map(function(d) {
return d.category;
})
);
x1
.domain(
data.map(function(d) {
return d.column;
})
)
.range([0, x0.bandwidth()])
.padding(0.2);
z.domain(Object.keys(data[0]).filter(x => x !== "category" && x !== "column"));
var keys = z.domain(); //["type1", "type2", "type3"];
var stackData = stack.keys(keys)(groupData);
y.domain([
0,
d3.max(groupData, function(d) {
return d.total;
})
]);
var serie = graph
.selectAll(".serie")
.data(stackData)
.enter()
.append("g")
.attr("class", "serie")
.attr("fill", function(d) {
return z(d.key);
});
serie
.selectAll("rect")
.data(function(d) {
return d;
})
.enter()
.append("rect")
.attr("class", "serie-rect")
.attr("transform", function(d) {
return "translate(" + x0(d.data.category) + ",0)";
})
.attr("x", function(d) {
return x1(d.data.column) + x1.bandwidth() / 2 - 20;
})
.attr("y", function(d) {
return y(d[1]);
})
.attr("height", function(d) {
return y(d[0]) - y(d[1]);
})
.attr("width", barwidth)
.on("mouseover", tip.show)
.on("mouseout", tip.hide);
graph
.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x0));
graph
.append("g")
.attr("class", "axis")
.call(d3.axisLeft(y).ticks(null, "s"));
#chart-area {
width: 600px;
overflow-x: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.9.1/d3-tip.min.js"></script>
<div id="chart-area"></div>
Upvotes: 1
Views: 1662
Reputation: 102174
Change the paddingOuter
in the innerScale. For instance:
x1.paddingOuter(0.5);
Here is the code with that change.
//DATA
var data = [
{
category: "test4",
type1: 100,
type2: 200,
type3: 0,
column: "column1"
},
{
category: "test4",
type1: 0,
type2: 0,
type3: 500,
column: "column2"
},
{
category: "test3",
type1: 100,
type2: 200,
type3: 0,
column: "column1"
},
{
category: "test3",
type1: 0,
type2: 0,
type3: 500,
column: "column2"
},
{
category: "test1",
type1: 100,
type2: 200,
type3: 0,
column: "column1"
},
{
category: "test1",
type1: 0,
type2: 0,
type3: 500,
column: "column2"
},
{
category: "test2",
type1: 150,
type2: 100,
type3: 0,
column: "column1"
},
{
category: "test2",
type1: 0,
type2: 0,
type3: 400,
column: "column2"
}
];
var groupData = d3
.nest()
.key(function(d) {
return d.column + d.category;
})
.rollup(function(v) {
return {
...v[0],
total: v[0].type1 + v[0].type2 + v[0].type3
};
})
.entries(data)
.map(function(d) {
return { ...d.value };
});
//INITIAL SETUP
var margin = { top: 30, right: 10, bottom: 50, left: 40 };
var width = groupData.length * 80 - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
var barwidth = 40;
var tip = d3
.tip()
.attr("class", "d3-tip")
.html(function(d) {
return "<span>Test</span>";
});
var graph = d3
.select("#chart-area")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
graph.call(tip);
var x0 = d3
.scaleBand()
.rangeRound([0, width])
.paddingInner(0.1);
var x1 = d3.scaleBand().padding(0.05);
var y = d3.scaleLinear().range([height, 0]);
var y1 = d3.scaleBand();
var z = d3.scaleOrdinal().range(["#98abc5", "#8a89a6"]);
var stack = d3.stack();
x0.domain(
data.map(function(d) {
return d.category;
})
);
x1
.domain(
data.map(function(d) {
return d.column;
})
)
.range([0, x0.bandwidth()])
.paddingOuter(0.5);
z.domain(Object.keys(data[0]).filter(x => x !== "category" && x !== "column"));
var keys = z.domain(); //["type1", "type2", "type3"];
var stackData = stack.keys(keys)(groupData);
y.domain([
0,
d3.max(groupData, function(d) {
return d.total;
})
]);
var serie = graph
.selectAll(".serie")
.data(stackData)
.enter()
.append("g")
.attr("class", "serie")
.attr("fill", function(d) {
return z(d.key);
});
serie
.selectAll("rect")
.data(function(d) {
return d;
})
.enter()
.append("rect")
.attr("class", "serie-rect")
.attr("transform", function(d) {
return "translate(" + x0(d.data.category) + ",0)";
})
.attr("x", function(d) {
return x1(d.data.column) + x1.bandwidth() / 2 - 20;
})
.attr("y", function(d) {
return y(d[1]);
})
.attr("height", function(d) {
return y(d[0]) - y(d[1]);
})
.attr("width", barwidth)
.on("mouseover", tip.show)
.on("mouseout", tip.hide);
graph
.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x0));
graph
.append("g")
.attr("class", "axis")
.call(d3.axisLeft(y).ticks(null, "s"));
#chart-area {
width: 600px;
overflow-x: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.9.1/d3-tip.min.js"></script>
<div id="chart-area"></div>
As you can see, this will simultaneously reduce the distance between the grouped bars and increase the distance among the groups (because, obviously, I'm not changing the range of the outer scale). Also, not related to your question: you're overwriting the padding in the inner scale.
Upvotes: 1