diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js index 0d4176f279a..cbac98e5130 100644 --- a/src/controllers/controller.bar.js +++ b/src/controllers/controller.bar.js @@ -447,6 +447,18 @@ export default class BarController extends DatasetController { head = base + size; } + const actualBase = baseValue || 0; + if (base === vScale.getPixelForValue(actualBase)) { + const halfGrid = vScale.getLineWidthForValue(actualBase) / 2; + if (size > 0) { + base += halfGrid; + size -= halfGrid; + } else if (size < 0) { + base -= halfGrid; + size += halfGrid; + } + } + return { size, base, diff --git a/src/core/core.scale.js b/src/core/core.scale.js index 19f1f26390e..5f2f9a543ea 100644 --- a/src/core/core.scale.js +++ b/src/core/core.scale.js @@ -1604,6 +1604,21 @@ export default class Scale extends Element { } } + getLineWidthForValue(value) { + const me = this; + const grid = me.options.grid; + if (!me._isVisible() || !grid.display) { + return 0; + } + const ticks = me.ticks; + const index = ticks.findIndex(t => t.value === value); + if (index >= 0) { + const opts = grid.setContext(me.getContext(index)); + return opts.lineWidth; + } + return 0; + } + /** * @protected */ diff --git a/test/fixtures/controller.bar/baseLine/bottom.js b/test/fixtures/controller.bar/baseLine/bottom.js new file mode 100644 index 00000000000..272b8e99b3b --- /dev/null +++ b/test/fixtures/controller.bar/baseLine/bottom.js @@ -0,0 +1,40 @@ +module.exports = { + config: { + type: 'bar', + data: { + labels: ['a', 'b'], + datasets: [{ + backgroundColor: '#AAFFCC', + borderColor: '#0000FF', + borderWidth: 1, + data: [1, 2] + }] + }, + options: { + scales: { + x: { + display: false + }, + y: { + ticks: { + display: false + }, + grid: { + color: function(context) { + return context.tick.value === 0 ? 'red' : 'transparent'; + }, + lineWidth: 5, + tickLength: 0 + }, + } + }, + maintainAspectRatio: false + } + }, + options: { + canvas: { + width: 128, + height: 128 + } + } +}; diff --git a/test/fixtures/controller.bar/baseLine/bottom.png b/test/fixtures/controller.bar/baseLine/bottom.png new file mode 100644 index 00000000000..d7107153bb0 Binary files /dev/null and b/test/fixtures/controller.bar/baseLine/bottom.png differ diff --git a/test/fixtures/controller.bar/baseLine/left.js b/test/fixtures/controller.bar/baseLine/left.js new file mode 100644 index 00000000000..56a68ce5479 --- /dev/null +++ b/test/fixtures/controller.bar/baseLine/left.js @@ -0,0 +1,41 @@ +module.exports = { + config: { + type: 'bar', + data: { + labels: ['a', 'b'], + datasets: [{ + backgroundColor: '#AAFFCC', + borderColor: '#0000FF', + borderWidth: 1, + data: [1, 2] + }] + }, + options: { + indexAxis: 'y', + scales: { + y: { + display: false + }, + x: { + ticks: { + display: false + }, + grid: { + color: function(context) { + return context.tick.value === 0 ? 'red' : 'transparent'; + }, + lineWidth: 5, + tickLength: 0 + }, + } + }, + maintainAspectRatio: false + } + }, + options: { + canvas: { + width: 128, + height: 128 + } + } +}; diff --git a/test/fixtures/controller.bar/baseLine/left.png b/test/fixtures/controller.bar/baseLine/left.png new file mode 100644 index 00000000000..ca5e1227b5c Binary files /dev/null and b/test/fixtures/controller.bar/baseLine/left.png differ diff --git a/test/fixtures/controller.bar/baseLine/mid-x.js b/test/fixtures/controller.bar/baseLine/mid-x.js new file mode 100644 index 00000000000..ef6beb5c97b --- /dev/null +++ b/test/fixtures/controller.bar/baseLine/mid-x.js @@ -0,0 +1,41 @@ +module.exports = { + config: { + type: 'bar', + data: { + labels: ['a', 'b'], + datasets: [{ + backgroundColor: '#AAFFCC', + borderColor: '#0000FF', + borderWidth: 1, + data: [1, -1] + }] + }, + options: { + indexAxis: 'y', + scales: { + y: { + display: false + }, + x: { + ticks: { + display: false + }, + grid: { + color: function(context) { + return context.tick.value === 0 ? 'red' : 'transparent'; + }, + lineWidth: 5, + tickLength: 0 + }, + } + }, + maintainAspectRatio: false + } + }, + options: { + canvas: { + width: 128, + height: 128 + } + } +}; diff --git a/test/fixtures/controller.bar/baseLine/mid-x.png b/test/fixtures/controller.bar/baseLine/mid-x.png new file mode 100644 index 00000000000..1f4feb2e36b Binary files /dev/null and b/test/fixtures/controller.bar/baseLine/mid-x.png differ diff --git a/test/fixtures/controller.bar/baseLine/mid-y.js b/test/fixtures/controller.bar/baseLine/mid-y.js new file mode 100644 index 00000000000..d01c00a12d8 --- /dev/null +++ b/test/fixtures/controller.bar/baseLine/mid-y.js @@ -0,0 +1,40 @@ +module.exports = { + config: { + type: 'bar', + data: { + labels: ['a', 'b'], + datasets: [{ + backgroundColor: '#AAFFCC', + borderColor: '#0000FF', + borderWidth: 1, + data: [1, -1] + }] + }, + options: { + scales: { + x: { + display: false + }, + y: { + ticks: { + display: false + }, + grid: { + color: function(context) { + return context.tick.value === 0 ? 'red' : 'transparent'; + }, + lineWidth: 5, + tickLength: 0 + }, + } + }, + maintainAspectRatio: false + } + }, + options: { + canvas: { + width: 128, + height: 128 + } + } +}; diff --git a/test/fixtures/controller.bar/baseLine/mid-y.png b/test/fixtures/controller.bar/baseLine/mid-y.png new file mode 100644 index 00000000000..88c21a15374 Binary files /dev/null and b/test/fixtures/controller.bar/baseLine/mid-y.png differ diff --git a/test/fixtures/controller.bar/baseLine/right.js b/test/fixtures/controller.bar/baseLine/right.js new file mode 100644 index 00000000000..1fc069f1f68 --- /dev/null +++ b/test/fixtures/controller.bar/baseLine/right.js @@ -0,0 +1,42 @@ +module.exports = { + config: { + type: 'bar', + data: { + labels: ['a', 'b'], + datasets: [{ + backgroundColor: '#AAFFCC', + borderColor: '#0000FF', + borderWidth: 1, + data: [-1, -2] + }] + }, + options: { + indexAxis: 'y', + scales: { + y: { + display: false + }, + x: { + ticks: { + display: false + }, + grid: { + color: function(context) { + return context.tick.value === 0 ? 'red' : 'transparent'; + }, + lineWidth: 5, + tickLength: 0, + borderWidth: 0 + }, + } + }, + maintainAspectRatio: false + } + }, + options: { + canvas: { + width: 128, + height: 128 + } + } +}; diff --git a/test/fixtures/controller.bar/baseLine/right.png b/test/fixtures/controller.bar/baseLine/right.png new file mode 100644 index 00000000000..2ad1dfdb3ea Binary files /dev/null and b/test/fixtures/controller.bar/baseLine/right.png differ diff --git a/test/fixtures/controller.bar/baseLine/top.js b/test/fixtures/controller.bar/baseLine/top.js new file mode 100644 index 00000000000..86a7a378d1e --- /dev/null +++ b/test/fixtures/controller.bar/baseLine/top.js @@ -0,0 +1,41 @@ +module.exports = { + config: { + type: 'bar', + data: { + labels: ['a', 'b'], + datasets: [{ + backgroundColor: '#AAFFCC', + borderColor: '#0000FF', + borderWidth: 1, + data: [-1, -2] + }] + }, + options: { + scales: { + x: { + display: false + }, + y: { + ticks: { + display: false + }, + grid: { + color: function(context) { + return context.tick.value === 0 ? 'red' : 'transparent'; + }, + borderWidth: 0, + lineWidth: 5, + tickLength: 0 + }, + } + }, + maintainAspectRatio: false + } + }, + options: { + canvas: { + width: 128, + height: 128 + } + } +}; diff --git a/test/fixtures/controller.bar/baseLine/top.png b/test/fixtures/controller.bar/baseLine/top.png new file mode 100644 index 00000000000..8472c0fbf0d Binary files /dev/null and b/test/fixtures/controller.bar/baseLine/top.png differ diff --git a/test/fixtures/controller.bar/baseLine/value-x.js b/test/fixtures/controller.bar/baseLine/value-x.js new file mode 100644 index 00000000000..557a8986385 --- /dev/null +++ b/test/fixtures/controller.bar/baseLine/value-x.js @@ -0,0 +1,42 @@ +module.exports = { + config: { + type: 'bar', + data: { + labels: ['a', 'b'], + datasets: [{ + backgroundColor: '#AAFFCC', + borderColor: '#0000FF', + borderWidth: 1, + data: [1, 3] + }] + }, + options: { + base: 2, + indexAxis: 'y', + scales: { + y: { + display: false + }, + x: { + ticks: { + display: false + }, + grid: { + color: function(context) { + return context.tick.value === 2 ? 'red' : 'transparent'; + }, + lineWidth: 5, + tickLength: 0 + }, + } + }, + maintainAspectRatio: false + } + }, + options: { + canvas: { + width: 128, + height: 128 + } + } +}; diff --git a/test/fixtures/controller.bar/baseLine/value-x.png b/test/fixtures/controller.bar/baseLine/value-x.png new file mode 100644 index 00000000000..1fd0161a55f Binary files /dev/null and b/test/fixtures/controller.bar/baseLine/value-x.png differ diff --git a/test/fixtures/controller.bar/baseLine/value-y.js b/test/fixtures/controller.bar/baseLine/value-y.js new file mode 100644 index 00000000000..caee084df6b --- /dev/null +++ b/test/fixtures/controller.bar/baseLine/value-y.js @@ -0,0 +1,41 @@ +module.exports = { + config: { + type: 'bar', + data: { + labels: ['a', 'b'], + datasets: [{ + backgroundColor: '#AAFFCC', + borderColor: '#0000FF', + borderWidth: 1, + data: [1, 3] + }] + }, + options: { + base: 2, + scales: { + x: { + display: false + }, + y: { + ticks: { + display: false + }, + grid: { + color: function(context) { + return context.tick.value === 2 ? 'red' : 'transparent'; + }, + lineWidth: 5, + tickLength: 0 + }, + } + }, + maintainAspectRatio: false + } + }, + options: { + canvas: { + width: 128, + height: 128 + } + } +}; diff --git a/test/fixtures/controller.bar/baseLine/value-y.png b/test/fixtures/controller.bar/baseLine/value-y.png new file mode 100644 index 00000000000..15fe7871013 Binary files /dev/null and b/test/fixtures/controller.bar/baseLine/value-y.png differ diff --git a/test/specs/controller.bar.tests.js b/test/specs/controller.bar.tests.js index 883a9ed58e1..6be8eb1ede7 100644 --- a/test/specs/controller.bar.tests.js +++ b/test/specs/controller.bar.tests.js @@ -1528,9 +1528,10 @@ describe('Chart.controllers.bar', function() { }); var data = chart.getDatasetMeta(0).data; + var halfBaseLine = chart.scales.y.getLineWidthForValue(0) / 2; - expect(data[0].base - minBarLength).toEqual(data[0].y); - expect(data[1].base + minBarLength).toEqual(data[1].y); + expect(data[0].base - minBarLength + halfBaseLine).toEqual(data[0].y); + expect(data[1].base + minBarLength - halfBaseLine).toEqual(data[1].y); }); it('minBarLength settings should be used on X axis on horizontal bar chart', function() { @@ -1547,9 +1548,10 @@ describe('Chart.controllers.bar', function() { }); var data = chart.getDatasetMeta(0).data; + var halfBaseLine = chart.scales.x.getLineWidthForValue(0) / 2; - expect(data[0].base + minBarLength).toEqual(data[0].x); - expect(data[1].base - minBarLength).toEqual(data[1].x); + expect(data[0].base + minBarLength - halfBaseLine).toEqual(data[0].x); + expect(data[1].base - minBarLength + halfBaseLine).toEqual(data[1].x); }); it('should respect the data visibility settings', function() { diff --git a/types/index.esm.d.ts b/types/index.esm.d.ts index 936c9f938fe..3a2f5b5832a 100644 --- a/types/index.esm.d.ts +++ b/types/index.esm.d.ts @@ -1195,6 +1195,12 @@ export interface Scale extends El * @return {string} */ getLabelForValue(value: number): string; + + /** + * Returns the grid line width at given value + */ + getLineWidthForValue(value: number): number; + /** * Returns the location of the given data point. Value can either be an index or a numerical value * The coordinate (0, 0) is at the upper-left corner of the canvas