Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added "bar.space" parameter to set space between bars in bar charts #2146

Merged
merged 1 commit into from
Aug 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions htdocs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ <h3>Area Chart</h3>
</div>
<div class="col-md-4">
<h3>Bar Chart</h3>
<a href="./samples/chart_bar_space.html">
Bar chart with spaces
</a>
<a href="./samples/chart_bar.html">
Bar chart with ordinary data
</a>
Expand Down
28 changes: 28 additions & 0 deletions htdocs/samples/chart_bar_space.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<html>
<head>
<link href="/css/c3.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="chart"></div>

<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="/js/c3.js"></script>
<script>

var generate = function () { return c3.generate({
data: {
columns: [
['data1', 30, 200, 100],
['data2', 50, 20, 10],
['data3', 150, 120, 110]
],
type: 'bar'
},
bar: {
space: 0.25
}
}); }, chart = generate();

</script>
</body>
</html>
152 changes: 152 additions & 0 deletions spec/shape.bar-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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));
});
});
});
1 change: 1 addition & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
9 changes: 5 additions & 4 deletions src/shape.bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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]
];
};
};
Expand Down