From e2f0648f5dedc8a233585d35a6d85e69943eeef8 Mon Sep 17 00:00:00 2001 From: Evert Timberg Date: Sat, 27 Mar 2021 13:24:15 -0400 Subject: [PATCH 1/2] Improved alignment of pixels in scales at low widths --- src/core/core.scale.js | 29 ++++++++++++++--------------- src/helpers/helpers.canvas.js | 2 +- test/specs/core.scale.tests.js | 5 ++++- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/core/core.scale.js b/src/core/core.scale.js index 3913ad30291..d5b8d365ce8 100644 --- a/src/core/core.scale.js +++ b/src/core/core.scale.js @@ -999,7 +999,6 @@ export default class Scale extends Element { const borderOpts = grid.setContext(me.getContext(0)); const axisWidth = borderOpts.drawBorder ? borderOpts.borderWidth : 0; - const axisHalfWidth = axisWidth / 2; const alignBorderValue = function(pixel) { return _alignPixel(chart, pixel, axisWidth); }; @@ -1009,26 +1008,26 @@ export default class Scale extends Element { if (position === 'top') { borderValue = alignBorderValue(me.bottom); ty1 = me.bottom - tl; - ty2 = borderValue - axisHalfWidth; - y1 = alignBorderValue(chartArea.top) + axisHalfWidth; + ty2 = borderValue; + y1 = alignBorderValue(chartArea.top); y2 = chartArea.bottom; } else if (position === 'bottom') { borderValue = alignBorderValue(me.top); y1 = chartArea.top; - y2 = alignBorderValue(chartArea.bottom) - axisHalfWidth; - ty1 = borderValue + axisHalfWidth; + y2 = alignBorderValue(chartArea.bottom); + ty1 = borderValue; ty2 = me.top + tl; } else if (position === 'left') { borderValue = alignBorderValue(me.right); tx1 = me.right - tl; - tx2 = borderValue - axisHalfWidth; - x1 = alignBorderValue(chartArea.left) + axisHalfWidth; + tx2 = borderValue; + x1 = alignBorderValue(chartArea.left); x2 = chartArea.right; } else if (position === 'right') { borderValue = alignBorderValue(me.left); x1 = chartArea.left; - x2 = alignBorderValue(chartArea.right) - axisHalfWidth; - tx1 = borderValue + axisHalfWidth; + x2 = alignBorderValue(chartArea.right); + tx1 = borderValue; tx2 = me.left + tl; } else if (axis === 'x') { if (position === 'center') { @@ -1041,7 +1040,7 @@ export default class Scale extends Element { y1 = chartArea.top; y2 = chartArea.bottom; - ty1 = borderValue + axisHalfWidth; + ty1 = borderValue; ty2 = ty1 + tl; } else if (axis === 'y') { if (position === 'center') { @@ -1052,7 +1051,7 @@ export default class Scale extends Element { borderValue = alignBorderValue(me.chart.scales[positionAxisID].getPixelForValue(value)); } - tx1 = borderValue - axisHalfWidth; + tx1 = borderValue; tx2 = tx1 - tl; x1 = chartArea.left; x2 = chartArea.right; @@ -1413,12 +1412,12 @@ export default class Scale extends Element { let x1, x2, y1, y2; if (me.isHorizontal()) { - x1 = _alignPixel(chart, me.left, axisWidth) - axisWidth / 2; - x2 = _alignPixel(chart, me.right, lastLineWidth) + lastLineWidth / 2; + x1 = _alignPixel(chart, me.left, axisWidth); + x2 = _alignPixel(chart, me.right, lastLineWidth); y1 = y2 = borderValue; } else { - y1 = _alignPixel(chart, me.top, axisWidth) - axisWidth / 2; - y2 = _alignPixel(chart, me.bottom, lastLineWidth) + lastLineWidth / 2; + y1 = _alignPixel(chart, me.top, axisWidth); + y2 = _alignPixel(chart, me.bottom, lastLineWidth); x1 = x2 = borderValue; } drawLine( diff --git a/src/helpers/helpers.canvas.js b/src/helpers/helpers.canvas.js index 0472bddb31b..8282b3a9425 100644 --- a/src/helpers/helpers.canvas.js +++ b/src/helpers/helpers.canvas.js @@ -102,7 +102,7 @@ export function _longestText(ctx, font, arrayOfThings, cache) { */ export function _alignPixel(chart, pixel, width) { const devicePixelRatio = chart.currentDevicePixelRatio; - const halfWidth = width / 2; + const halfWidth = width !== 0 ? Math.max(width / 2, 0.5) : 0; return Math.round((pixel - halfWidth) * devicePixelRatio) / devicePixelRatio + halfWidth; } diff --git a/test/specs/core.scale.tests.js b/test/specs/core.scale.tests.js index 93a04618607..54ee4b3e3c7 100644 --- a/test/specs/core.scale.tests.js +++ b/test/specs/core.scale.tests.js @@ -199,7 +199,10 @@ describe('Core.scale', function() { chart.draw(); expect(yScale.ctx.getCalls().filter(function(x) { - return x.name === 'moveTo' && x.args[0] === 1; + return x.name === 'moveTo' && x.args[0] === 0.5; + }).filter(function(x, i, arr) { + // Remove the extra point at the end + return i !== arr.length - 1; }).map(function(x) { return x.args[1]; })).toEqual(test.expected); From 5f7f7655858665b28a816c4afe33a83a4333a9d9 Mon Sep 17 00:00:00 2001 From: Evert Timberg Date: Sat, 27 Mar 2021 14:14:47 -0400 Subject: [PATCH 2/2] Undo scale changes --- src/core/core.scale.js | 29 +++++++++++++++-------------- test/specs/core.scale.tests.js | 5 +---- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/core/core.scale.js b/src/core/core.scale.js index d5b8d365ce8..3913ad30291 100644 --- a/src/core/core.scale.js +++ b/src/core/core.scale.js @@ -999,6 +999,7 @@ export default class Scale extends Element { const borderOpts = grid.setContext(me.getContext(0)); const axisWidth = borderOpts.drawBorder ? borderOpts.borderWidth : 0; + const axisHalfWidth = axisWidth / 2; const alignBorderValue = function(pixel) { return _alignPixel(chart, pixel, axisWidth); }; @@ -1008,26 +1009,26 @@ export default class Scale extends Element { if (position === 'top') { borderValue = alignBorderValue(me.bottom); ty1 = me.bottom - tl; - ty2 = borderValue; - y1 = alignBorderValue(chartArea.top); + ty2 = borderValue - axisHalfWidth; + y1 = alignBorderValue(chartArea.top) + axisHalfWidth; y2 = chartArea.bottom; } else if (position === 'bottom') { borderValue = alignBorderValue(me.top); y1 = chartArea.top; - y2 = alignBorderValue(chartArea.bottom); - ty1 = borderValue; + y2 = alignBorderValue(chartArea.bottom) - axisHalfWidth; + ty1 = borderValue + axisHalfWidth; ty2 = me.top + tl; } else if (position === 'left') { borderValue = alignBorderValue(me.right); tx1 = me.right - tl; - tx2 = borderValue; - x1 = alignBorderValue(chartArea.left); + tx2 = borderValue - axisHalfWidth; + x1 = alignBorderValue(chartArea.left) + axisHalfWidth; x2 = chartArea.right; } else if (position === 'right') { borderValue = alignBorderValue(me.left); x1 = chartArea.left; - x2 = alignBorderValue(chartArea.right); - tx1 = borderValue; + x2 = alignBorderValue(chartArea.right) - axisHalfWidth; + tx1 = borderValue + axisHalfWidth; tx2 = me.left + tl; } else if (axis === 'x') { if (position === 'center') { @@ -1040,7 +1041,7 @@ export default class Scale extends Element { y1 = chartArea.top; y2 = chartArea.bottom; - ty1 = borderValue; + ty1 = borderValue + axisHalfWidth; ty2 = ty1 + tl; } else if (axis === 'y') { if (position === 'center') { @@ -1051,7 +1052,7 @@ export default class Scale extends Element { borderValue = alignBorderValue(me.chart.scales[positionAxisID].getPixelForValue(value)); } - tx1 = borderValue; + tx1 = borderValue - axisHalfWidth; tx2 = tx1 - tl; x1 = chartArea.left; x2 = chartArea.right; @@ -1412,12 +1413,12 @@ export default class Scale extends Element { let x1, x2, y1, y2; if (me.isHorizontal()) { - x1 = _alignPixel(chart, me.left, axisWidth); - x2 = _alignPixel(chart, me.right, lastLineWidth); + 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); - y2 = _alignPixel(chart, me.bottom, lastLineWidth); + y1 = _alignPixel(chart, me.top, axisWidth) - axisWidth / 2; + y2 = _alignPixel(chart, me.bottom, lastLineWidth) + lastLineWidth / 2; x1 = x2 = borderValue; } drawLine( diff --git a/test/specs/core.scale.tests.js b/test/specs/core.scale.tests.js index 54ee4b3e3c7..93a04618607 100644 --- a/test/specs/core.scale.tests.js +++ b/test/specs/core.scale.tests.js @@ -199,10 +199,7 @@ describe('Core.scale', function() { chart.draw(); expect(yScale.ctx.getCalls().filter(function(x) { - return x.name === 'moveTo' && x.args[0] === 0.5; - }).filter(function(x, i, arr) { - // Remove the extra point at the end - return i !== arr.length - 1; + return x.name === 'moveTo' && x.args[0] === 1; }).map(function(x) { return x.args[1]; })).toEqual(test.expected);