-
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
Implement scale label padding #4646
Conversation
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 code looks ok. Is there any way to unit test this?
Dunno. All I could offer right now is a screenshot with padding applied. |
ping @etimberg any suggestion how to implement a unit test? Would love to get this in. |
@andig there are some tests that compare screenshots of the canvas to a known image. Would those work here or would they be too finicky? @simonbrunel any ideas? |
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.
Images comparison will not work correctly since it will contain text (and so will be rendered differently on each browsers). Maybe you can test the layout box dimensions (scale top, bottom, width, height, minHeight, minWidth, etc.
) and verify that the padding is correctly taken in account?
docs/axes/labelling.md
Outdated
@@ -15,6 +15,7 @@ The scale label configuration is nested under the scale configuration in the `sc | |||
| `fontFamily` | `String` | `"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"` | Font family for the scale title, follows CSS font-family options. | |||
| `fontSize` | `Number` | `12` | Font size for scale title. | |||
| `fontStyle` | `String` | `'normal'` | Font style for the scale title, follows CSS font-style options (i.e. normal, italic, oblique, initial, inherit). | |||
| `padding` | `Number` or `Object`` | `0` | Padding to apply around scale labels. Only `top` and `bottom` are implemented. |
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.
One extra `
at `Object``
src/core/core.scale.js
Outdated
@@ -396,10 +397,11 @@ module.exports = function(Chart) { | |||
|
|||
// Are we showing a title for the scale? | |||
if (scaleLabelOpts.display && display) { | |||
var padding = scaleLabelPadding.top + scaleLabelPadding.bottom; |
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.
var padding = scaleLabelPadding.height;
@simonbrunel will make the desired changes.
Any example where/howto getbthat box? From the rendered chart or maybe any of the events? Another idea: would it make sense to get rid of the |
That's weird, I thought @etimberg implemented multi-line support for the scale label. For the unit test(s), maybe something like: var chart = acquireChart({
type: 'line',
data: { ... },
options: {
// ...
scales: {
xAxes: [{
id: 'x',
scaleLabel: {
padding: ...
}
//...
}]
}
}
});
var scale = chart.scales.x;
expect(scale.top).toBe(...);
expect(scale.bottom).toBe(...);
expect(scale.minSize).toEqual({
height: ...,
width: ...
}); |
Might have gotten this wrong. I was referring to https://github.com/chartjs/Chart.js/blob/master/src/core/core.scale.js#L833 Would it be ok to replace this with default padding instead to make sure there is only one source for applying padding? |
I think this option has been introduced in 2.7 (@etimberg), so still time to remove it. I agree that it doesn't make sense to have it if we don't support multi-line, I agree to remove it. At some point, this option will be re-added when we will implement multi-line. |
Line height was added in #4387 to address an earlier bug that padding would also solve |
He're the current looks of the result. With scale labels: Without scale labels: With scale labels but without ticks:
|
@etimberg in order to advance this PR I'd need some help with the failing tests. Some are obvious (need to add the padding to the expected config, need to add the padding to the layout calculations), some are not (e.g. calculating "halfway" scale positions). It also seems a lot of effort to do these changed manually all over the place. Is this really the right way to go? |
src/core/core.scale.js
Outdated
@@ -35,7 +35,11 @@ defaults._set('scale', { | |||
// actual label | |||
labelString: '', | |||
|
|||
lineHeight: 1.2 | |||
// top/bottom padding | |||
padding: { |
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.
Should be 0
to avoid changing existing charts?
docs/axes/labelling.md
Outdated
| `fontColor` | Color | `'#666'` | Font color for scale title. | ||
| `fontFamily` | `String` | `"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"` | Font family for the scale title, follows CSS font-family options. | ||
| `fontSize` | `Number` | `12` | Font size for scale title. | ||
| `fontStyle` | `String` | `'normal'` | Font style for the scale title, follows CSS font-style options (i.e. normal, italic, oblique, initial, inherit). | ||
| `padding` | `Number` or `Object` | `0` | Padding to apply around scale labels. Only `top` and `bottom` are implemented. The `top` direction always refers to the edge of the label that is furthest aways from the chart center, i.e. for a bottom axis this `top` padding is applied at the bottom of the label. |
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.
"The
top
direction always refers to the edge of the label that is furthest aways from the chart center, i.e. for a bottom axis thistop
padding is applied at the bottom of the label."
Seems quite confusing to me, padding should not depend on the scale position but only on the label rotation, so in case of position: bottom
, padding top is the edge "closer" to the chart center.
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 understand. This is however the only way to set padding as global default without having different default per axis position since the bottom axis basically has reversed orientation.Can still be overridden on per-axis basis by user.
da9c53e
to
27e14a4
Compare
ping @simonbrunel updated as discussed:
|
For the fixture test, you might need to tweak the JSON file to remove the extra spacing to obtain the same result as the image, or regenerate the PNG (details in #3988). For the other failing test, I'm not sure. We should write tests with minimal features (only the one that needs to be tested) and in most case the scale should be hidden. That would prevent this kind of changes. |
I will rebase this once #4694 is merged and will wait for how the updated fixture performs on travis. |
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.
@@ -435,16 +445,17 @@ module.exports = function(Chart) { | |||
// TODO - improve this calculation | |||
var labelHeight = (sinRotation * largestTextWidth) | |||
+ (tickFont.size * tallestLabelHeightInLines) | |||
+ (lineSpace * tallestLabelHeightInLines); | |||
+ (lineSpace * (tallestLabelHeightInLines - 1)) |
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.
What's the reason for this change? It looks equivalent to the old 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.
It is actually equivalent but prepares for implementing tick label padding. lineSpace
is only needed lines-1 times. The last lineSpace
is really outer padding and could indeed be any other value.
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.
Gotcha
scaleLabelX = isLeft ? me.left + halfLineHeight : me.right - halfLineHeight; | ||
scaleLabelX = isLeft | ||
? me.left + halfLineHeight + scaleLabelPadding.top | ||
: me.right - halfLineHeight - scaleLabelPadding.top; |
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.
[nit] would put halfLineHeight + scaleLabeePadding.top
in a local var for better minification since it's use 3 times
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.
Can do but it looks kinda asymetric and hard to grasp:
var halfLineHeight = parseLineHeight(scaleLabel) / 2;
var halfLineHeightPlusTopPadding = halfLineHeight + scaleLabelPadding.top;
if (isHorizontal) {
scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width
scaleLabelY = options.position === 'bottom'
? me.bottom - halfLineHeight - scaleLabelPadding.bottom
: me.top + halfLineHeightPlusTopPadding;
} else {
var isLeft = options.position === 'left';
scaleLabelX = isLeft
? me.left + halfLineHeightPlusTopPadding
: me.right - halfLineHeightPlusTopPadding;
scaleLabelY = me.top + ((me.bottom - me.top) / 2);
rotation = isLeft ? -0.5 * Math.PI : 0.5 * Math.PI;
}
Is this really desired?
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.
fair enough, that's not better. Lets leave it as is
@simonbrunel I am ok with this in either version. it really depends on when 2.7 goes out the door |
Fixes #4505, currently missing tests (no idea how to implement those- help needed) and docs (will update asap).
I've also noticed that top/down labels seem to apply half line margin/padding, left/right axes don't- I assume that's desired?
Update I've also create a simple plugin that takes care of applying configurable padding to all "inner" axis per direction https://www.npmjs.com/package/chartjs-plugin-axispadding
Thanks @simonbrunel for the defered plugin- I've used that as skeleton.