diff --git a/src/core/core.scale.js b/src/core/core.scale.js index 95ff5f8b84c..5b793a6f382 100644 --- a/src/core/core.scale.js +++ b/src/core/core.scale.js @@ -1009,7 +1009,7 @@ export default class Scale extends Element { const tl = getTickMarkLength(grid); const items = []; - const borderOpts = grid.setContext(me.getContext(0)); + const borderOpts = grid.setContext(me.getContext()); const axisWidth = borderOpts.drawBorder ? borderOpts.borderWidth : 0; const axisHalfWidth = axisWidth / 2; const alignBorderValue = function(pixel) { @@ -1414,9 +1414,6 @@ export default class Scale extends Element { const me = this; const grid = me.options.grid; const ctx = me.ctx; - const chart = me.chart; - const borderOpts = grid.setContext(me.getContext()); - const axisWidth = grid.drawBorder ? borderOpts.borderWidth : 0; const items = me._gridLineItems || (me._gridLineItems = me._computeGridLineItems(chartArea)); let i, ilen; @@ -1463,27 +1460,42 @@ export default class Scale extends Element { } } } + } - if (axisWidth) { - // Draw the line at the edge of the axis - const lastLineWidth = borderOpts.lineWidth; - const borderValue = me._borderValue; - let x1, x2, y1, y2; + /** + * @protected + */ + drawBorder() { + const me = this; + const {chart, ctx, options: {grid}} = me; + const borderOpts = grid.setContext(me.getContext()); + const axisWidth = grid.drawBorder ? borderOpts.borderWidth : 0; + if (!axisWidth) { + return; + } + const lastLineWidth = grid.setContext(me.getContext(0)).lineWidth; + const borderValue = me._borderValue; + let x1, x2, y1, y2; - if (me.isHorizontal()) { - x1 = _alignPixel(chart, me.left, axisWidth) - axisWidth / 2; - x2 = _alignPixel(chart, me.right, lastLineWidth) + lastLineWidth / 2; - y1 = y2 = borderValue; - } else { - y1 = _alignPixel(chart, me.top, axisWidth) - axisWidth / 2; - y2 = _alignPixel(chart, me.bottom, lastLineWidth) + lastLineWidth / 2; - x1 = x2 = borderValue; - } - drawLine( - {x: x1, y: y1}, - {x: x2, y: y2}, - {width: axisWidth, color: borderOpts.borderColor}); + if (me.isHorizontal()) { + x1 = _alignPixel(chart, me.left, axisWidth) - axisWidth / 2; + x2 = _alignPixel(chart, me.right, lastLineWidth) + lastLineWidth / 2; + y1 = y2 = borderValue; + } else { + y1 = _alignPixel(chart, me.top, axisWidth) - axisWidth / 2; + y2 = _alignPixel(chart, me.bottom, lastLineWidth) + lastLineWidth / 2; + x1 = x2 = borderValue; } + ctx.save(); + ctx.lineWidth = borderOpts.borderWidth; + ctx.strokeStyle = borderOpts.borderColor; + + ctx.beginPath(); + ctx.moveTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.stroke(); + + ctx.restore(); } /** @@ -1571,6 +1583,7 @@ export default class Scale extends Element { me.drawBackground(); me.drawGrid(chartArea); + me.drawBorder(); me.drawTitle(); me.drawLabels(chartArea); } @@ -1585,7 +1598,7 @@ export default class Scale extends Element { const tz = opts.ticks && opts.ticks.z || 0; const gz = opts.grid && opts.grid.z || 0; - if (!me._isVisible() || tz === gz || me.draw !== Scale.prototype.draw) { + if (!me._isVisible() || me.draw !== Scale.prototype.draw) { // backward compatibility: draw has been overridden by custom scale return [{ z: tz, @@ -1602,6 +1615,11 @@ export default class Scale extends Element { me.drawGrid(chartArea); me.drawTitle(); } + }, { + z: gz + 1, // TODO, v4 move border options to its own object and add z + draw() { + me.drawBorder(); + } }, { z: tz, draw(chartArea) { diff --git a/src/scales/scale.radialLinear.js b/src/scales/scale.radialLinear.js index a12acb2b105..7be1d220c35 100644 --- a/src/scales/scale.radialLinear.js +++ b/src/scales/scale.radialLinear.js @@ -506,6 +506,11 @@ export default class RadialLinearScale extends LinearScaleBase { } } + /** + * @protected + */ + drawBorder() {} + /** * @protected */ diff --git a/test/fixtures/core.scale/grid/border-over-grid.js b/test/fixtures/core.scale/grid/border-over-grid.js new file mode 100644 index 00000000000..785a40456bc --- /dev/null +++ b/test/fixtures/core.scale/grid/border-over-grid.js @@ -0,0 +1,37 @@ +module.exports = { + config: { + type: 'scatter', + options: { + scales: { + x: { + position: {y: 0}, + min: -10, + max: 10, + grid: { + borderColor: 'black', + borderWidth: 5, + color: 'lightGray', + lineWidth: 3, + }, + ticks: { + display: false + }, + }, + y: { + position: {x: 0}, + min: -10, + max: 10, + grid: { + borderColor: 'black', + borderWidth: 5, + color: 'lightGray', + lineWidth: 3, + }, + ticks: { + display: false + }, + } + } + } + } +}; diff --git a/test/fixtures/core.scale/grid/border-over-grid.png b/test/fixtures/core.scale/grid/border-over-grid.png new file mode 100644 index 00000000000..256e5743aa7 Binary files /dev/null and b/test/fixtures/core.scale/grid/border-over-grid.png differ diff --git a/test/fixtures/core.scale/grid/colors.js b/test/fixtures/core.scale/grid/colors.js new file mode 100644 index 00000000000..e5765a170c2 --- /dev/null +++ b/test/fixtures/core.scale/grid/colors.js @@ -0,0 +1,38 @@ +module.exports = { + config: { + type: 'line', + data: { + labels: ['1', '2', '3', '4', '5', '6'], + datasets: [{ + label: '# of Votes', + data: [12, 19, 3, 5, 2, 3] + }], + }, + options: { + scales: { + x: { + ticks: { + display: false + }, + grid: { + borderColor: 'blue', + borderWidth: 2, + color: 'green', + drawTicks: false, + } + }, + y: { + ticks: { + display: false + }, + grid: { + borderColor: 'black', + borderWidth: 2, + color: 'red', + drawTicks: false, + } + } + } + } + } +}; diff --git a/test/fixtures/core.scale/grid/colors.png b/test/fixtures/core.scale/grid/colors.png new file mode 100644 index 00000000000..231441d8e68 Binary files /dev/null and b/test/fixtures/core.scale/grid/colors.png differ diff --git a/test/fixtures/scale.category/ticks-from-data.png b/test/fixtures/scale.category/ticks-from-data.png index 8bc1d66e936..4a65b49fe11 100644 Binary files a/test/fixtures/scale.category/ticks-from-data.png and b/test/fixtures/scale.category/ticks-from-data.png differ diff --git a/test/specs/core.scale.tests.js b/test/specs/core.scale.tests.js index 93a04618607..04ce097edb9 100644 --- a/test/specs/core.scale.tests.js +++ b/test/specs/core.scale.tests.js @@ -433,7 +433,7 @@ describe('Core.scale', function() { }); describe('_layers', function() { - it('should default to one layer', function() { + it('should default to three layers', function() { var chart = window.acquireChart({ type: 'line', options: { @@ -446,7 +446,7 @@ describe('Core.scale', function() { }); var scale = chart.scales.x; - expect(scale._layers().length).toEqual(1); + expect(scale._layers().length).toEqual(3); }); it('should default to one layer for custom scales', function() { @@ -482,30 +482,7 @@ describe('Core.scale', function() { expect(scale._layers()[0].z).toEqual(20); }); - it('should default to one layer when z is equal between ticks and grid', function() { - var chart = window.acquireChart({ - type: 'line', - options: { - scales: { - x: { - type: 'linear', - ticks: { - z: 10 - }, - grid: { - z: 10 - } - } - } - } - }); - - var scale = chart.scales.x; - expect(scale._layers().length).toEqual(1); - }); - - - it('should return 2 layers when z is not equal between ticks and grid', function() { + it('should return 3 layers when z is not equal between ticks and grid', function() { var chart = window.acquireChart({ type: 'line', options: { @@ -520,7 +497,7 @@ describe('Core.scale', function() { } }); - expect(chart.scales.x._layers().length).toEqual(2); + expect(chart.scales.x._layers().length).toEqual(3); chart = window.acquireChart({ type: 'line', @@ -536,7 +513,7 @@ describe('Core.scale', function() { } }); - expect(chart.scales.x._layers().length).toEqual(2); + expect(chart.scales.x._layers().length).toEqual(3); chart = window.acquireChart({ type: 'line', @@ -555,7 +532,7 @@ describe('Core.scale', function() { } }); - expect(chart.scales.x._layers().length).toEqual(2); + expect(chart.scales.x._layers().length).toEqual(3); });