mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
Implement scale label padding (#4646)
This commit is contained in:
parent
543c31d549
commit
ea703a54bf
@ -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` | `4` | Padding to apply around scale labels. Only `top` and `bottom` are implemented.
|
||||
|
||||
## Creating Custom Tick Formats
|
||||
|
||||
|
||||
@ -36,7 +36,14 @@ defaults._set('scale', {
|
||||
// actual label
|
||||
labelString: '',
|
||||
|
||||
lineHeight: 1.2
|
||||
// line height
|
||||
lineHeight: 1.2,
|
||||
|
||||
// top/bottom padding
|
||||
padding: {
|
||||
top: 4,
|
||||
bottom: 4
|
||||
}
|
||||
},
|
||||
|
||||
// label settings
|
||||
@ -391,7 +398,6 @@ module.exports = function(Chart) {
|
||||
|
||||
var tickFont = parseFontOptions(tickOpts);
|
||||
var tickMarkLength = opts.gridLines.tickMarkLength;
|
||||
var scaleLabelLineHeight = parseLineHeight(scaleLabelOpts);
|
||||
|
||||
// Width
|
||||
if (isHorizontal) {
|
||||
@ -410,10 +416,14 @@ module.exports = function(Chart) {
|
||||
|
||||
// Are we showing a title for the scale?
|
||||
if (scaleLabelOpts.display && display) {
|
||||
var scaleLabelLineHeight = parseLineHeight(scaleLabelOpts);
|
||||
var scaleLabelPadding = helpers.options.toPadding(scaleLabelOpts.padding);
|
||||
var deltaHeight = scaleLabelLineHeight + scaleLabelPadding.height;
|
||||
|
||||
if (isHorizontal) {
|
||||
minSize.height += scaleLabelLineHeight;
|
||||
minSize.height += deltaHeight;
|
||||
} else {
|
||||
minSize.width += scaleLabelLineHeight;
|
||||
minSize.width += deltaHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@ -435,16 +445,17 @@ module.exports = function(Chart) {
|
||||
// TODO - improve this calculation
|
||||
var labelHeight = (sinRotation * largestTextWidth)
|
||||
+ (tickFont.size * tallestLabelHeightInLines)
|
||||
+ (lineSpace * tallestLabelHeightInLines);
|
||||
+ (lineSpace * (tallestLabelHeightInLines - 1))
|
||||
+ lineSpace; // padding
|
||||
|
||||
minSize.height = Math.min(me.maxHeight, minSize.height + labelHeight + tickPadding);
|
||||
me.ctx.font = tickFont.font;
|
||||
|
||||
me.ctx.font = tickFont.font;
|
||||
var firstLabelWidth = computeTextSize(me.ctx, labels[0], tickFont.font);
|
||||
var lastLabelWidth = computeTextSize(me.ctx, labels[labels.length - 1], tickFont.font);
|
||||
|
||||
// Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned which means that the right padding is dominated
|
||||
// by the font height
|
||||
// Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned
|
||||
// which means that the right padding is dominated by the font height
|
||||
if (me.labelRotation !== 0) {
|
||||
me.paddingLeft = opts.position === 'bottom' ? (cosRotation * firstLabelWidth) + 3 : (cosRotation * lineSpace) + 3; // add 3 px to move away from canvas edges
|
||||
me.paddingRight = opts.position === 'bottom' ? (cosRotation * lineSpace) + 3 : (cosRotation * lastLabelWidth) + 3;
|
||||
@ -453,15 +464,18 @@ module.exports = function(Chart) {
|
||||
me.paddingRight = lastLabelWidth / 2 + 3;
|
||||
}
|
||||
} else {
|
||||
// A vertical axis is more constrained by the width. Labels are the dominant factor here, so get that length first
|
||||
// Account for padding
|
||||
|
||||
// A vertical axis is more constrained by the width. Labels are the
|
||||
// dominant factor here, so get that length first and account for padding
|
||||
if (tickOpts.mirror) {
|
||||
largestTextWidth = 0;
|
||||
} else {
|
||||
largestTextWidth += tickPadding;
|
||||
// use lineSpace for consistency with horizontal axis
|
||||
// tickPadding is not implemented for horizontal
|
||||
largestTextWidth += tickPadding + lineSpace;
|
||||
}
|
||||
|
||||
minSize.width = Math.min(me.maxWidth, minSize.width + largestTextWidth);
|
||||
|
||||
me.paddingTop = tickFont.size / 2;
|
||||
me.paddingBottom = tickFont.size / 2;
|
||||
}
|
||||
@ -663,6 +677,7 @@ module.exports = function(Chart) {
|
||||
|
||||
var scaleLabelFontColor = helpers.valueOrDefault(scaleLabel.fontColor, globalDefaults.defaultFontColor);
|
||||
var scaleLabelFont = parseFontOptions(scaleLabel);
|
||||
var scaleLabelPadding = helpers.options.toPadding(scaleLabel.padding);
|
||||
var labelRotationRadians = helpers.toRadians(me.labelRotation);
|
||||
|
||||
var itemsToDraw = [];
|
||||
@ -840,10 +855,14 @@ module.exports = function(Chart) {
|
||||
|
||||
if (isHorizontal) {
|
||||
scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width
|
||||
scaleLabelY = options.position === 'bottom' ? me.bottom - halfLineHeight : me.top + halfLineHeight;
|
||||
scaleLabelY = options.position === 'bottom'
|
||||
? me.bottom - halfLineHeight - scaleLabelPadding.bottom
|
||||
: me.top + halfLineHeight + scaleLabelPadding.top;
|
||||
} else {
|
||||
var isLeft = options.position === 'left';
|
||||
scaleLabelX = isLeft ? me.left + halfLineHeight : me.right - halfLineHeight;
|
||||
scaleLabelX = isLeft
|
||||
? me.left + halfLineHeight + scaleLabelPadding.top
|
||||
: me.right - halfLineHeight - scaleLabelPadding.top;
|
||||
scaleLabelY = me.top + ((me.bottom - me.top) / 2);
|
||||
rotation = isLeft ? -0.5 * Math.PI : 0.5 * Math.PI;
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
@ -128,11 +128,7 @@ describe('Core helper tests', function() {
|
||||
},
|
||||
position: 'right',
|
||||
offset: false,
|
||||
scaleLabel: {
|
||||
display: false,
|
||||
labelString: '',
|
||||
lineHeight: 1.2
|
||||
},
|
||||
scaleLabel: Chart.defaults.scale.scaleLabel,
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
minRotation: 0,
|
||||
@ -170,11 +166,7 @@ describe('Core helper tests', function() {
|
||||
},
|
||||
position: 'left',
|
||||
offset: false,
|
||||
scaleLabel: {
|
||||
display: false,
|
||||
labelString: '',
|
||||
lineHeight: 1.2
|
||||
},
|
||||
scaleLabel: Chart.defaults.scale.scaleLabel,
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
minRotation: 0,
|
||||
|
||||
@ -1,3 +1,22 @@
|
||||
describe('Core.scale', function() {
|
||||
describe('auto', jasmine.specsFromFixtures('core.scale'));
|
||||
|
||||
it('should provide default scale label options', function() {
|
||||
expect(Chart.defaults.scale.scaleLabel).toEqual({
|
||||
// display property
|
||||
display: false,
|
||||
|
||||
// actual label
|
||||
labelString: '',
|
||||
|
||||
// actual label
|
||||
lineHeight: 1.2,
|
||||
|
||||
// top/bottom padding
|
||||
padding: {
|
||||
top: 4,
|
||||
bottom: 4
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -143,7 +143,7 @@ describe('Core.Tooltip', function() {
|
||||
}]
|
||||
}));
|
||||
|
||||
expect(tooltip._view.x).toBeCloseToPixel(263);
|
||||
expect(tooltip._view.x).toBeCloseToPixel(266);
|
||||
expect(tooltip._view.y).toBeCloseToPixel(155);
|
||||
});
|
||||
|
||||
@ -341,7 +341,7 @@ describe('Core.Tooltip', function() {
|
||||
}]
|
||||
}));
|
||||
|
||||
expect(tooltip._view.x).toBeCloseToPixel(263);
|
||||
expect(tooltip._view.x).toBeCloseToPixel(266);
|
||||
expect(tooltip._view.y).toBeCloseToPixel(312);
|
||||
});
|
||||
|
||||
@ -494,7 +494,7 @@ describe('Core.Tooltip', function() {
|
||||
}]
|
||||
}));
|
||||
|
||||
expect(tooltip._view.x).toBeCloseToPixel(211);
|
||||
expect(tooltip._view.x).toBeCloseToPixel(214);
|
||||
expect(tooltip._view.y).toBeCloseToPixel(190);
|
||||
});
|
||||
|
||||
@ -574,7 +574,7 @@ describe('Core.Tooltip', function() {
|
||||
}]
|
||||
}));
|
||||
|
||||
expect(tooltip._view.x).toBeCloseToPixel(263);
|
||||
expect(tooltip._view.x).toBeCloseToPixel(266);
|
||||
expect(tooltip._view.y).toBeCloseToPixel(155);
|
||||
});
|
||||
|
||||
|
||||
@ -30,11 +30,7 @@ describe('Category scale tests', function() {
|
||||
},
|
||||
position: 'bottom',
|
||||
offset: false,
|
||||
scaleLabel: {
|
||||
display: false,
|
||||
labelString: '',
|
||||
lineHeight: 1.2
|
||||
},
|
||||
scaleLabel: Chart.defaults.scale.scaleLabel,
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
minRotation: 0,
|
||||
@ -215,7 +211,7 @@ describe('Category scale tests', function() {
|
||||
});
|
||||
|
||||
var xScale = chart.scales.xScale0;
|
||||
expect(xScale.getPixelForValue(0, 0, 0)).toBeCloseToPixel(23);
|
||||
expect(xScale.getPixelForValue(0, 0, 0)).toBeCloseToPixel(23 + 6); // plus lineHeight
|
||||
expect(xScale.getValueForPixel(23)).toBe(0);
|
||||
|
||||
expect(xScale.getPixelForValue(0, 4, 0)).toBeCloseToPixel(487);
|
||||
@ -224,7 +220,7 @@ describe('Category scale tests', function() {
|
||||
xScale.options.offset = true;
|
||||
chart.update();
|
||||
|
||||
expect(xScale.getPixelForValue(0, 0, 0)).toBeCloseToPixel(69);
|
||||
expect(xScale.getPixelForValue(0, 0, 0)).toBeCloseToPixel(69 + 6); // plus lineHeight
|
||||
expect(xScale.getValueForPixel(69)).toBe(0);
|
||||
|
||||
expect(xScale.getPixelForValue(0, 4, 0)).toBeCloseToPixel(441);
|
||||
@ -258,8 +254,8 @@ describe('Category scale tests', function() {
|
||||
});
|
||||
|
||||
var xScale = chart.scales.xScale0;
|
||||
expect(xScale.getPixelForValue('tick_1', 0, 0)).toBeCloseToPixel(23);
|
||||
expect(xScale.getPixelForValue('tick_1', 1, 0)).toBeCloseToPixel(139);
|
||||
expect(xScale.getPixelForValue('tick_1', 0, 0)).toBeCloseToPixel(23 + 6); // plus lineHeight
|
||||
expect(xScale.getPixelForValue('tick_1', 1, 0)).toBeCloseToPixel(143);
|
||||
});
|
||||
|
||||
it ('Should get the correct pixel for a value when horizontal and zoomed', function() {
|
||||
@ -293,13 +289,13 @@ describe('Category scale tests', function() {
|
||||
});
|
||||
|
||||
var xScale = chart.scales.xScale0;
|
||||
expect(xScale.getPixelForValue(0, 1, 0)).toBeCloseToPixel(23);
|
||||
expect(xScale.getPixelForValue(0, 1, 0)).toBeCloseToPixel(23 + 6); // plus lineHeight
|
||||
expect(xScale.getPixelForValue(0, 3, 0)).toBeCloseToPixel(496);
|
||||
|
||||
xScale.options.offset = true;
|
||||
chart.update();
|
||||
|
||||
expect(xScale.getPixelForValue(0, 1, 0)).toBeCloseToPixel(102);
|
||||
expect(xScale.getPixelForValue(0, 1, 0)).toBeCloseToPixel(102 + 6); // plus lineHeight
|
||||
expect(xScale.getPixelForValue(0, 3, 0)).toBeCloseToPixel(417);
|
||||
});
|
||||
|
||||
|
||||
@ -28,11 +28,7 @@ describe('Linear Scale', function() {
|
||||
},
|
||||
position: 'left',
|
||||
offset: false,
|
||||
scaleLabel: {
|
||||
display: false,
|
||||
labelString: '',
|
||||
lineHeight: 1.2
|
||||
},
|
||||
scaleLabel: Chart.defaults.scale.scaleLabel,
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
minRotation: 0,
|
||||
@ -695,8 +691,8 @@ describe('Linear Scale', function() {
|
||||
|
||||
var xScale = chart.scales.xScale0;
|
||||
expect(xScale.getPixelForValue(1, 0, 0)).toBeCloseToPixel(501); // right - paddingRight
|
||||
expect(xScale.getPixelForValue(-1, 0, 0)).toBeCloseToPixel(31); // left + paddingLeft
|
||||
expect(xScale.getPixelForValue(0, 0, 0)).toBeCloseToPixel(266); // halfway*/
|
||||
expect(xScale.getPixelForValue(-1, 0, 0)).toBeCloseToPixel(31 + 6); // left + paddingLeft + lineSpace
|
||||
expect(xScale.getPixelForValue(0, 0, 0)).toBeCloseToPixel(266 + 6 / 2); // halfway*/
|
||||
|
||||
expect(xScale.getValueForPixel(501)).toBeCloseTo(1, 1e-2);
|
||||
expect(xScale.getValueForPixel(31)).toBeCloseTo(-1, 1e-2);
|
||||
@ -754,7 +750,7 @@ describe('Linear Scale', function() {
|
||||
expect(xScale.paddingBottom).toBeCloseToPixel(0);
|
||||
expect(xScale.paddingLeft).toBeCloseToPixel(0);
|
||||
expect(xScale.paddingRight).toBeCloseToPixel(0);
|
||||
expect(xScale.width).toBeCloseToPixel(468);
|
||||
expect(xScale.width).toBeCloseToPixel(468 - 6); // minus lineSpace
|
||||
expect(xScale.height).toBeCloseToPixel(28);
|
||||
|
||||
var yScale = chart.scales.yScale0;
|
||||
@ -762,7 +758,7 @@ describe('Linear Scale', function() {
|
||||
expect(yScale.paddingBottom).toBeCloseToPixel(0);
|
||||
expect(yScale.paddingLeft).toBeCloseToPixel(0);
|
||||
expect(yScale.paddingRight).toBeCloseToPixel(0);
|
||||
expect(yScale.width).toBeCloseToPixel(30);
|
||||
expect(yScale.width).toBeCloseToPixel(30 + 6); // plus lineSpace
|
||||
expect(yScale.height).toBeCloseToPixel(452);
|
||||
|
||||
// Extra size when scale label showing
|
||||
@ -774,15 +770,15 @@ describe('Linear Scale', function() {
|
||||
expect(xScale.paddingBottom).toBeCloseToPixel(0);
|
||||
expect(xScale.paddingLeft).toBeCloseToPixel(0);
|
||||
expect(xScale.paddingRight).toBeCloseToPixel(0);
|
||||
expect(xScale.width).toBeCloseToPixel(454);
|
||||
expect(xScale.height).toBeCloseToPixel(42);
|
||||
expect(xScale.width).toBeCloseToPixel(440);
|
||||
expect(xScale.height).toBeCloseToPixel(50);
|
||||
|
||||
expect(yScale.paddingTop).toBeCloseToPixel(0);
|
||||
expect(yScale.paddingBottom).toBeCloseToPixel(0);
|
||||
expect(yScale.paddingLeft).toBeCloseToPixel(0);
|
||||
expect(yScale.paddingRight).toBeCloseToPixel(0);
|
||||
expect(yScale.width).toBeCloseToPixel(44);
|
||||
expect(yScale.height).toBeCloseToPixel(438);
|
||||
expect(yScale.width).toBeCloseToPixel(58);
|
||||
expect(yScale.height).toBeCloseToPixel(430);
|
||||
});
|
||||
|
||||
it('should fit correctly when display is turned off', function() {
|
||||
|
||||
@ -27,11 +27,7 @@ describe('Logarithmic Scale tests', function() {
|
||||
},
|
||||
position: 'left',
|
||||
offset: false,
|
||||
scaleLabel: {
|
||||
display: false,
|
||||
labelString: '',
|
||||
lineHeight: 1.2
|
||||
},
|
||||
scaleLabel: Chart.defaults.scale.scaleLabel,
|
||||
ticks: {
|
||||
beginAtZero: false,
|
||||
minRotation: 0,
|
||||
@ -720,9 +716,9 @@ describe('Logarithmic Scale tests', function() {
|
||||
|
||||
var xScale = chart.scales.xScale;
|
||||
expect(xScale.getPixelForValue(80, 0, 0)).toBeCloseToPixel(495); // right - paddingRight
|
||||
expect(xScale.getPixelForValue(1, 0, 0)).toBeCloseToPixel(37); // left + paddingLeft
|
||||
expect(xScale.getPixelForValue(10, 0, 0)).toBeCloseToPixel(278); // halfway
|
||||
expect(xScale.getPixelForValue(0, 0, 0)).toBeCloseToPixel(37); // 0 is invalid, put it on the left.
|
||||
expect(xScale.getPixelForValue(1, 0, 0)).toBeCloseToPixel(37 + 6); // left + paddingLeft + lineSpace
|
||||
expect(xScale.getPixelForValue(10, 0, 0)).toBeCloseToPixel(278 + 6 / 2); // halfway
|
||||
expect(xScale.getPixelForValue(0, 0, 0)).toBeCloseToPixel(37 + 6); // 0 is invalid, put it on the left.
|
||||
|
||||
expect(xScale.getValueForPixel(495)).toBeCloseToPixel(80);
|
||||
expect(xScale.getValueForPixel(48)).toBeCloseTo(1, 1e-4);
|
||||
|
||||
@ -40,11 +40,7 @@ describe('Test the radial linear scale', function() {
|
||||
},
|
||||
position: 'chartArea',
|
||||
offset: false,
|
||||
scaleLabel: {
|
||||
display: false,
|
||||
labelString: '',
|
||||
lineHeight: 1.2
|
||||
},
|
||||
scaleLabel: Chart.defaults.scale.scaleLabel,
|
||||
ticks: {
|
||||
backdropColor: 'rgba(255,255,255,0.75)',
|
||||
backdropPaddingY: 2,
|
||||
|
||||
@ -73,11 +73,7 @@ describe('Time scale tests', function() {
|
||||
},
|
||||
position: 'bottom',
|
||||
offset: false,
|
||||
scaleLabel: {
|
||||
display: false,
|
||||
labelString: '',
|
||||
lineHeight: 1.2
|
||||
},
|
||||
scaleLabel: Chart.defaults.scale.scaleLabel,
|
||||
bounds: 'data',
|
||||
distribution: 'linear',
|
||||
ticks: {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user