-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
Fix the rounding issue of floating point numbers in category scale #5880
Conversation
1e80895
to
221784c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @nagix, it looks good.
This scale.draw
method is quite complex, we would need to clean it deeper (not in this PR of course). Still, a few suggestions that I think would make the impacted code simpler.
src/core/core.helpers.js
Outdated
* @param {Number} lineWidth - A line width. | ||
* @returns {Number} The aligned line pixel value. | ||
*/ | ||
helpers.alignLinePixel = function(chart, linePixel, lineWidth) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would declare this method private for sure to not have to deal with deprecation if we realize we don't need it anymore or if we want to change its signature, and maybe rename it for something more generic and shorter:
helpers._alignPixel = function(chart, pixel, width) {
// ...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed
src/core/core.scale.js
Outdated
var alignedTop = helpers.alignLinePixel(chart, me.top, axisWidth); | ||
var alignedBottom = helpers.alignLinePixel(chart, me.bottom, axisWidth); | ||
|
||
var xTickStart, xTickEnd, yTickStart, yTickEnd; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm not wrong, depending on the scale orientation, only half of these variables (including the new aligned*
) are effectively used so I think we could simplify for something like:
var axisWidth = helpers.valueAtIndexOrDefault(gridLines.lineWidth, 0, 0);
var alignPixel = helpers._alignPixel;
var aligned, tickStart, tickEnd;
if (position === 'top') {
aligned = alignPixel(chart, me.bottom, axisWidth);
tickStart = me.bottom - tl;
tickEnd = aligned - axisWidth / 2;
} else if (position === 'bottom') {
aligned = alignPixel(chart, me.top, axisWidth);
tickStart = aligned + axisWidth / 2;
tickEnd = me.top + tl;
} else if (position === 'left') {
aligned = alignPixel(chart, me.right, axisWidth);
tickStart = me.right - tl;
tickEnd = aligned - axisWidth / 2;
} else {
aligned = alignPixel(chart, me.left, axisWidth);
tickStart = aligned + axisWidth / 2;
tickEnd = me.left + tl;
}
Feel free to rename aligned
for whatever you think it's better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this simplification. I renamed it to borderValue
as it stores the position of the axis border.
src/core/core.scale.js
Outdated
y1 = y2 = options.position === 'top' ? me.bottom : me.top; | ||
y1 += aliasPixel; | ||
y2 += aliasPixel; | ||
y1 = y2 = position === 'top' ? alignedBottom : alignedTop; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we are computing too many values here and based on my previous comment, I think we can rewrite this part as:
var x1, x2, y1, y2;
if (isHorizontal) {
x1 = alignPixel(chart, me.left, firstLineWidth) - firstLineWidth / 2;
x2 = alignPixel(chart, me.right, lastLineWidth) + lastLineWidth / 2;
y1 = y2 = aligned;
} else {
y1 = alignPixel(chart, me.top, firstLineWidth) - firstLineWidth / 2;
y2 = alignPixel(chart, me.bottom, lastLineWidth) + lastLineWidth / 2;
x1 = x2 = aligned;
}
src/core/core.scale.js
Outdated
context.moveTo(x1, y1); | ||
context.lineTo(x2, y2); | ||
context.stroke(); | ||
if (axisWidth) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! do we also need to compute all the code above if at the end we draw nothing? or should we break earlier, for example at line 933 (if (gridLines.drawBorder && axisWidth)
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realized axisWidth
has to be set to 0
if gridLines.drawBorder
is false
, so I moved this logic at the beginning of draw
.
- Remove `Math.round` in the category scale code - Add `helpers._alignPixel` to align grid/tick/axis border lines - Fix grid/tick/axis border line calculation - Add a check of the width of the axis border - Refactor core.scale code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Hi, I'm wondering what version of Chart.js this is? Reason being I need to use a version of angular-chart that contains this fix and I'm hoping there is a corresponding version there. Thanks! |
This PR is in Chart.js 2.8.0 |
…hartjs#5880) - Remove `Math.round` in the category scale code - Add `helpers._alignPixel` to align grid/tick/axis border lines - Fix grid/tick/axis border line calculation - Add a check of the width of the axis border - Refactor core.scale code
This PR fixes following problems.
barPercentage
andcategoryPercentage
set to 1 (Bar Graph Render Issue in 2.5.0 #3916, [BUG] Spacing between vertical bars with percentages set to 1 #3964)The following changes are made in this PR.
Math.round
in the category scale code is removed. In my opinion, rounding should be done not ingetPixelForTick
but in drawing functions to avoid detection errors.Master: https://jsfiddle.net/nagix/52o0qn47/
This PR: https://jsfiddle.net/nagix/upv21qto/
Fixes #3916
Fixes #3964
Fixes #4640
Fixes #5297
Fixes #5431
Fixes #5532
Fixes #5576
Fixes #5797