diff --git a/htdocs/index.html b/htdocs/index.html
index cf6847e2e..6f12df0e2 100644
--- a/htdocs/index.html
+++ b/htdocs/index.html
@@ -44,6 +44,9 @@
Bar Chart
+
+ Bar chart with spaces
+
Bar chart with ordinary data
diff --git a/htdocs/samples/chart_bar_space.html b/htdocs/samples/chart_bar_space.html
new file mode 100644
index 000000000..00e48a945
--- /dev/null
+++ b/htdocs/samples/chart_bar_space.html
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spec/shape.bar-spec.js b/spec/shape.bar-spec.js
index 838625c6f..f8f6b3c15 100644
--- a/spec/shape.bar-spec.js
+++ b/spec/shape.bar-spec.js
@@ -174,4 +174,156 @@ describe('c3 chart shape bar', function () {
});
+ describe('bar spacing', function() {
+
+ var createArgs = function(spacing) {
+ return {
+ size: {
+ width: 500
+ },
+ data: {
+ columns: [
+ ['data1', 30, 200, 100],
+ ['data2', 50, 20, 10],
+ ['data3', 150, 120, 110],
+ ['data4', 12, 24, 20 ]
+ ],
+ type: 'bar',
+ groups: [
+ [ 'data1', 'data4' ]
+ ]
+ },
+ bar: {
+ space: spacing
+ }
+ };
+ };
+
+ var getBBox = function(selector) {
+ return d3.select(selector).node().getBBox();
+ };
+
+ var getBarContainerWidth = function() {
+ return parseInt(getBBox('.c3-chart-bars').width);
+ };
+
+ var getBarContainerOffset = function() {
+ return parseInt(getBBox('.c3-chart-bars').x);
+ };
+
+ var getBarBBox = function(name, idx) {
+ return getBBox('.c3-target-' + name + ' .c3-bar-' + (idx || 0));
+ };
+
+ var getBarWidth = function(name, idx) {
+ return parseInt(getBarBBox(name, idx).width);
+ };
+
+ var getBarOffset = function(name1, name2, idx) {
+ var bbox1 = getBarBBox(name1, idx);
+ var bbox2 = getBarBBox(name2, idx);
+ return parseInt(bbox2.x - (bbox1.x + bbox1.width));
+ };
+
+ it('should set bar spacing to 0', function () {
+ args = createArgs(0);
+ expect(true).toBeTruthy();
+ });
+
+ it('should display the bars without any spacing', function () {
+ // all bars should have the same width
+ expect(getBarWidth('data1', 0)).toEqual(30);
+ expect(getBarWidth('data2', 0)).toEqual(30);
+ expect(getBarWidth('data3', 0)).toEqual(30);
+ expect(getBarWidth('data1', 1)).toEqual(30);
+ expect(getBarWidth('data2', 1)).toEqual(30);
+ expect(getBarWidth('data3', 1)).toEqual(30);
+ expect(getBarWidth('data1', 2)).toEqual(30);
+ expect(getBarWidth('data2', 2)).toEqual(30);
+ expect(getBarWidth('data3', 2)).toEqual(30);
+
+ // all offsets should be the same
+ expect(getBarOffset('data1', 'data2', 0)).toEqual(0);
+ expect(getBarOffset('data2', 'data3', 0)).toEqual(0);
+ expect(getBarOffset('data1', 'data2', 1)).toEqual(0);
+ expect(getBarOffset('data2', 'data3', 1)).toEqual(0);
+ expect(getBarOffset('data1', 'data2', 2)).toEqual(0);
+ expect(getBarOffset('data2', 'data3', 2)).toEqual(0);
+
+ // default width/offset of the container for this chart
+ expect(getBarContainerWidth()).toEqual(396);
+ expect(getBarContainerOffset()).toEqual(31);
+ });
+
+ it('should set bar spacing to 0.25', function () {
+ args = createArgs(0.25);
+ expect(true).toBeTruthy();
+ });
+
+ it('should display the bars with a spacing ratio of 0.25', function () {
+ // with bar_space of 0.25, the space between bars is
+ // expected to be 25% of the original bar's width
+ // which is ~7
+
+ // expect all bars to be the same width
+ expect(getBarWidth('data1', 0)).toEqual(22);
+ expect(getBarWidth('data2', 0)).toEqual(22);
+ expect(getBarWidth('data3', 0)).toEqual(22);
+ expect(getBarWidth('data1', 1)).toEqual(22);
+ expect(getBarWidth('data2', 1)).toEqual(22);
+ expect(getBarWidth('data3', 1)).toEqual(22);
+ expect(getBarWidth('data1', 2)).toEqual(22);
+ expect(getBarWidth('data2', 2)).toEqual(22);
+ expect(getBarWidth('data3', 2)).toEqual(22);
+
+ // all offsets should be the same
+ expect(getBarOffset('data1', 'data2', 0)).toEqual(7);
+ expect(getBarOffset('data2', 'data3', 0)).toEqual(7);
+ expect(getBarOffset('data1', 'data2', 1)).toEqual(7);
+ expect(getBarOffset('data2', 'data3', 1)).toEqual(7);
+ expect(getBarOffset('data1', 'data2', 2)).toEqual(7);
+ expect(getBarOffset('data2', 'data3', 2)).toEqual(7);
+
+ // expect the container to shrink a little because of
+ // the offsets from the first/last chart
+ // we add/subtract 1 because of approximation due to rounded values
+ expect(getBarContainerWidth()).toEqual(396 - 7 - 1);
+ expect(getBarContainerOffset()).toEqual(31 + (parseInt(7 / 2) + 1));
+ });
+
+ it('should set bar spacing to 0.5', function () {
+ args = createArgs(0.5);
+ expect(true).toBeTruthy();
+ });
+
+ it('should display the bars with a spacing ratio of 0.5', function () {
+ // with bar_space of 0.5, the space between bars is
+ // expected to be 50% of the original bar's width
+ // which is ~15
+
+ // expect all bars to be the same width
+ expect(getBarWidth('data1', 0)).toEqual(15);
+ expect(getBarWidth('data2', 0)).toEqual(15);
+ expect(getBarWidth('data3', 0)).toEqual(15);
+ expect(getBarWidth('data1', 1)).toEqual(15);
+ expect(getBarWidth('data2', 1)).toEqual(15);
+ expect(getBarWidth('data3', 1)).toEqual(15);
+ expect(getBarWidth('data1', 2)).toEqual(15);
+ expect(getBarWidth('data2', 2)).toEqual(15);
+ expect(getBarWidth('data3', 2)).toEqual(15);
+
+ // all offsets should be the same
+ expect(getBarOffset('data1', 'data2', 0)).toEqual(15);
+ expect(getBarOffset('data2', 'data3', 0)).toEqual(15);
+ expect(getBarOffset('data1', 'data2', 1)).toEqual(15);
+ expect(getBarOffset('data2', 'data3', 1)).toEqual(15);
+ expect(getBarOffset('data1', 'data2', 2)).toEqual(15);
+ expect(getBarOffset('data2', 'data3', 2)).toEqual(15);
+
+ // expect the container to shrink a little because of
+ // the offsets from the first/last chart
+ expect(getBarContainerWidth()).toEqual(396 - 15);
+ expect(getBarContainerOffset()).toEqual(31 + parseInt(15 / 2));
+ });
+ });
});
diff --git a/src/config.js b/src/config.js
index 14565bf85..d95e2eced 100644
--- a/src/config.js
+++ b/src/config.js
@@ -170,6 +170,7 @@ c3_chart_internal_fn.getDefaultConfig = function () {
bar_width_ratio: 0.6,
bar_width_max: undefined,
bar_zerobased: true,
+ bar_space: 0,
// area
area_zerobased: true,
area_above: false,
diff --git a/src/shape.bar.js b/src/shape.bar.js
index 7bf538f0c..e71f89f82 100644
--- a/src/shape.bar.js
+++ b/src/shape.bar.js
@@ -97,6 +97,7 @@ c3_chart_internal_fn.generateGetBarPoints = function (barIndices, isSub) {
barX = $$.getShapeX(barW, barTargetsNum, barIndices, !!isSub),
barY = $$.getShapeY(!!isSub),
barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub),
+ barSpaceOffset = barW * ($$.config.bar_space / 2),
yScale = isSub ? $$.getSubYScale : $$.getYScale;
return function (d, i) {
var y0 = yScale.call($$, d.id)(0),
@@ -108,10 +109,10 @@ c3_chart_internal_fn.generateGetBarPoints = function (barIndices, isSub) {
}
// 4 points that make a bar
return [
- [posX, offset],
- [posX, posY - (y0 - offset)],
- [posX + barW, posY - (y0 - offset)],
- [posX + barW, offset]
+ [posX + barSpaceOffset, offset],
+ [posX + barSpaceOffset, posY - (y0 - offset)],
+ [posX + barW - barSpaceOffset, posY - (y0 - offset)],
+ [posX + barW - barSpaceOffset, offset]
];
};
};