| `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
// actual label
labelString: '',
- lineHeight: 1.2
+ // line height
+ lineHeight: 1.2,
+
+ // top/bottom padding
+ padding: {
+ top: 4,
+ bottom: 4
+ }
},
// label settings
var tickFont = parseFontOptions(tickOpts);
var tickMarkLength = opts.gridLines.tickMarkLength;
- var scaleLabelLineHeight = parseLineHeight(scaleLabelOpts);
// Width
if (isHorizontal) {
// 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;
}
}
// 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;
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;
}
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 = [];
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;
}
},
position: 'right',
offset: false,
- scaleLabel: {
- display: false,
- labelString: '',
- lineHeight: 1.2
- },
+ scaleLabel: Chart.defaults.scale.scaleLabel,
ticks: {
beginAtZero: false,
minRotation: 0,
},
position: 'left',
offset: false,
- scaleLabel: {
- display: false,
- labelString: '',
- lineHeight: 1.2
- },
+ scaleLabel: Chart.defaults.scale.scaleLabel,
ticks: {
beginAtZero: false,
minRotation: 0,
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
+ }
+ });
+ });
});
}]
}));
- expect(tooltip._view.x).toBeCloseToPixel(263);
+ expect(tooltip._view.x).toBeCloseToPixel(266);
expect(tooltip._view.y).toBeCloseToPixel(155);
});
}]
}));
- expect(tooltip._view.x).toBeCloseToPixel(263);
+ expect(tooltip._view.x).toBeCloseToPixel(266);
expect(tooltip._view.y).toBeCloseToPixel(312);
});
}]
}));
- expect(tooltip._view.x).toBeCloseToPixel(211);
+ expect(tooltip._view.x).toBeCloseToPixel(214);
expect(tooltip._view.y).toBeCloseToPixel(190);
});
}]
}));
- expect(tooltip._view.x).toBeCloseToPixel(263);
+ expect(tooltip._view.x).toBeCloseToPixel(266);
expect(tooltip._view.y).toBeCloseToPixel(155);
});
},
position: 'bottom',
offset: false,
- scaleLabel: {
- display: false,
- labelString: '',
- lineHeight: 1.2
- },
+ scaleLabel: Chart.defaults.scale.scaleLabel,
ticks: {
beginAtZero: false,
minRotation: 0,
});
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);
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);
});
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() {
});
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);
});
},
position: 'left',
offset: false,
- scaleLabel: {
- display: false,
- labelString: '',
- lineHeight: 1.2
- },
+ scaleLabel: Chart.defaults.scale.scaleLabel,
ticks: {
beginAtZero: false,
minRotation: 0,
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);
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;
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
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() {
},
position: 'left',
offset: false,
- scaleLabel: {
- display: false,
- labelString: '',
- lineHeight: 1.2
- },
+ scaleLabel: Chart.defaults.scale.scaleLabel,
ticks: {
beginAtZero: false,
minRotation: 0,
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);
},
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,
},
position: 'bottom',
offset: false,
- scaleLabel: {
- display: false,
- labelString: '',
- lineHeight: 1.2
- },
+ scaleLabel: Chart.defaults.scale.scaleLabel,
bounds: 'data',
distribution: 'linear',
ticks: {