Skip to content
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

Merged
merged 1 commit into from Sep 10, 2017
Merged

Implement scale label padding #4646

merged 1 commit into from Sep 10, 2017

Conversation

andig
Copy link
Contributor

@andig andig commented Aug 11, 2017

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.

Copy link
Member

@etimberg etimberg left a 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?

@andig
Copy link
Contributor Author

andig commented Aug 12, 2017

Dunno. All I could offer right now is a screenshot with padding applied.

@andig
Copy link
Contributor Author

andig commented Aug 16, 2017

ping @etimberg any suggestion how to implement a unit test? Would love to get this in.

@etimberg
Copy link
Member

@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?

Copy link
Member

@simonbrunel simonbrunel left a 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?

@@ -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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One extra ` at `Object``

@@ -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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var padding = scaleLabelPadding.height;

@andig
Copy link
Contributor Author

andig commented Aug 17, 2017

@simonbrunel will make the desired changes.

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?

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 lineHeightoption and use the padding instead? Would mean defaulting padding (maybe limited to horizontal axes) to half font size split top/bottom. Downside: takes away multi-line labels but those don‘t seem supported anyway.
Reason I‘m asking is that he linehight is already implemented as hardcoded padding top/bottom padding anyway?

@simonbrunel
Copy link
Member

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: ...
});

@andig
Copy link
Contributor Author

andig commented Aug 17, 2017

That's weird, I thought @etimberg implemented multi-line support for the scale label.

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?

@simonbrunel
Copy link
Member

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.

@etimberg
Copy link
Member

Line height was added in #4387 to address an earlier bug that padding would also solve

@andig
Copy link
Contributor Author

andig commented Aug 19, 2017

He're the current looks of the result.

With scale labels:

screen shot 2017-08-19 at 14 14 09

Without scale labels:

screen shot 2017-08-19 at 14 23 10

With scale labels but without ticks:

screen shot 2017-08-21 at 10 42 14

padding is now the only option to apply spacing around the scales. The only exception is if no scale label is display an additional half line height is added to the min tick dimenions to make sure axes don't stick together. Previously, this was only available for horizontal axes.

@andig
Copy link
Contributor Author

andig commented Aug 21, 2017

@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?

@@ -35,7 +35,11 @@ defaults._set('scale', {
// actual label
labelString: '',

lineHeight: 1.2
// top/bottom padding
padding: {
Copy link
Member

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?

| `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.
Copy link
Member

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 this top 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.

image

Copy link
Contributor Author

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.

@andig andig force-pushed the scale-padding branch 3 times, most recently from da9c53e to 27e14a4 Compare August 21, 2017 11:25
@andig
Copy link
Contributor Author

andig commented Aug 21, 2017

ping @simonbrunel updated as discussed:

  • Could you kindly take a look at the remaining test failures? One is the fixture I don't know nothing about.
  • The other is with stacked bars. I'd expect the bar width to get a little smaller due to y axis padding, however it only seems to fail for some bars which is weird?

@simonbrunel
Copy link
Member

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.

@andig
Copy link
Contributor Author

andig commented Aug 24, 2017

I will rebase this once #4694 is merged and will wait for how the updated fixture performs on travis.

Copy link
Member

@simonbrunel simonbrunel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @andig.

@etimberg should this be in 2.7 or 2.8?

@@ -435,16 +445,17 @@ module.exports = function(Chart) {
// TODO - improve this calculation
var labelHeight = (sinRotation * largestTextWidth)
+ (tickFont.size * tallestLabelHeightInLines)
+ (lineSpace * tallestLabelHeightInLines);
+ (lineSpace * (tallestLabelHeightInLines - 1))
Copy link
Member

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

Copy link
Contributor Author

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.

Copy link
Member

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;
Copy link
Member

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

Copy link
Contributor Author

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?

Copy link
Member

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

@etimberg
Copy link
Member

etimberg commented Sep 2, 2017

@simonbrunel I am ok with this in either version. it really depends on when 2.7 goes out the door

@simonbrunel simonbrunel added this to the Version 2.7 milestone Sep 10, 2017
@etimberg etimberg merged commit ea703a5 into chartjs:master Sep 10, 2017
@simonbrunel simonbrunel deleted the scale-padding branch September 10, 2017 17:18
yofreke pushed a commit to yofreke/Chart.js that referenced this pull request Dec 30, 2017
exwm pushed a commit to exwm/Chart.js that referenced this pull request Apr 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants