Skip to content

Commit

Permalink
Add support for line height CSS values
Browse files Browse the repository at this point in the history
The title plugin and scale title now accept lineHeight specified using unitless value (1.4), length ('1.4em' or '12px'), percentage ('200%') or keyword ('normal' === 1.2). The line height parsing has been refactored under the 'Chart.helpers.options' namespace. Also fix incorrect text position in the title plugin.

https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
  • Loading branch information
simonbrunel committed Jul 19, 2017
1 parent 3bb31ca commit 9dea44a
Show file tree
Hide file tree
Showing 14 changed files with 107 additions and 25 deletions.
2 changes: 1 addition & 1 deletion docs/axes/labelling.md
Expand Up @@ -10,7 +10,7 @@ The scale label configuration is nested under the scale configuration in the `sc
| -----| ---- | --------| -----------
| `display` | `Boolean` | `false` | If true, display the axis title.
| `labelString` | `String` | `''` | The text for the title. (i.e. "# of People" or "Response Choices").
| `lineHeight` | `Number` | `` | Height of an individual line of text. If not defined, the font size is used.
| `lineHeight` | `Number|String` | `1.5` | Height of an individual line of text (see [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/line-height))
| `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.
Expand Down
2 changes: 1 addition & 1 deletion docs/configuration/title.md
Expand Up @@ -14,7 +14,7 @@ The title configuration is passed into the `options.title` namespace. The global
| `fontColor` | Color | `'#666'` | Font color
| `fontStyle` | `String` | `'bold'` | Font style
| `padding` | `Number` | `10` | Number of pixels to add above and below the title text.
| `lineHeight` | `Number` | `undefined` | Height of line of text. If not specified, the `fontSize` is used.
| `lineHeight` | `Number|String` | `1.2` | Height of an individual line of text (see [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/line-height))
| `text` | `String/String[]` | `''` | Title text to display. If specified as an array, text is rendered on multiple lines.

### Position
Expand Down
16 changes: 12 additions & 4 deletions src/core/core.scale.js
Expand Up @@ -28,11 +28,13 @@ defaults._set('scale', {

// scale label
scaleLabel: {
// display property
display: false,

// actual label
labelString: '',

// display property
display: false,
lineHeight: 1.5
},

// label settings
Expand Down Expand Up @@ -77,6 +79,12 @@ module.exports = function(Chart) {
};
}

function parseLineHeight(options) {
return helpers.options.toLineHeight(
helpers.valueOrDefault(options.lineHeight, 1.2),
helpers.valueOrDefault(options.fontSize, defaults.global.defaultFontSize));
}

Chart.Scale = Chart.Element.extend({
/**
* Get the padding needed for the scale
Expand Down Expand Up @@ -310,8 +318,8 @@ module.exports = function(Chart) {
var isHorizontal = me.isHorizontal();

var tickFont = parseFontOptions(tickOpts);
var scaleLabelLineHeight = helpers.valueOrDefault(scaleLabelOpts.lineHeight, parseFontOptions(scaleLabelOpts).size * 1.5);
var tickMarkLength = opts.gridLines.tickMarkLength;
var scaleLabelLineHeight = parseLineHeight(scaleLabelOpts);

// Width
if (isHorizontal) {
Expand Down Expand Up @@ -738,7 +746,7 @@ module.exports = function(Chart) {
var scaleLabelX;
var scaleLabelY;
var rotation = 0;
var halfLineHeight = helpers.valueOrDefault(scaleLabel.lineHeight, scaleLabelFont.size) / 2;
var halfLineHeight = parseLineHeight(scaleLabel) / 2;

if (isHorizontal) {
scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width
Expand Down
35 changes: 35 additions & 0 deletions src/helpers/helpers.options.js
@@ -0,0 +1,35 @@
'use strict';

/**
* @namespace Chart.helpers.options
*/
module.exports = {
/**
* Converts the given line height `value` in pixels for a specific font `size`.
* @param {Number|String} value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em').
* @param {Number} size - The font size (in pixels) used to resolve relative `value`.
* @returns {Number} The effective line height in pixels (size * 1.2 if value is invalid).
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height
* @since 2.7.0
*/
toLineHeight: function(value, size) {
var matches = (''+value).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);
if (!matches || matches[1] === 'normal') {
return size * 1.2;
}

value = parseFloat(matches[2]);

switch (matches[3]) {
case 'px':
return value;
case '%':
value /= 100;
break;
default:
break;
}

return size * value;
}
};
1 change: 1 addition & 0 deletions src/helpers/index.js
Expand Up @@ -3,4 +3,5 @@
module.exports = require('./helpers.core');
module.exports.easing = require('./helpers.easing');
module.exports.canvas = require('./helpers.canvas');
module.exports.options = require('./helpers.options');
module.exports.time = require('./helpers.time');
10 changes: 6 additions & 4 deletions src/plugins/plugin.title.js
Expand Up @@ -8,6 +8,7 @@ defaults._set('global', {
display: false,
fontStyle: 'bold',
fullWidth: true,
lineHeight: 1.2,
padding: 10,
position: 'top',
text: '',
Expand Down Expand Up @@ -114,7 +115,7 @@ module.exports = function(Chart) {
fontSize = valueOrDefault(opts.fontSize, defaults.global.defaultFontSize),
minSize = me.minSize,
lineCount = helpers.isArray(opts.text) ? opts.text.length : 1,
lineHeight = valueOrDefault(opts.lineHeight, fontSize),
lineHeight = helpers.options.toLineHeight(opts.lineHeight, fontSize),
textSize = display ? (lineCount * lineHeight) + (opts.padding * 2) : 0;

if (me.isHorizontal()) {
Expand Down Expand Up @@ -150,7 +151,8 @@ module.exports = function(Chart) {
fontStyle = valueOrDefault(opts.fontStyle, globalDefaults.defaultFontStyle),
fontFamily = valueOrDefault(opts.fontFamily, globalDefaults.defaultFontFamily),
titleFont = helpers.fontString(fontSize, fontStyle, fontFamily),
lineHeight = valueOrDefault(opts.lineHeight, fontSize),
lineHeight = helpers.options.toLineHeight(opts.lineHeight, fontSize),
offset = lineHeight/2 + opts.padding,
rotation = 0,
titleX,
titleY,
Expand All @@ -166,10 +168,10 @@ module.exports = function(Chart) {
// Horizontal
if (me.isHorizontal()) {
titleX = left + ((right - left) / 2); // midpoint of the width
titleY = top + ((bottom - top) / 2); // midpoint of the height
titleY = top + offset;
maxWidth = right - left;
} else {
titleX = opts.position === 'left' ? left + (fontSize / 2) : right - (fontSize / 2);
titleX = opts.position === 'left' ? left + offset : right - offset;
titleY = top + ((bottom - top) / 2);
maxWidth = bottom - top;
rotation = Math.PI * (opts.position === 'left' ? -0.5 : 0.5);
Expand Down
6 changes: 4 additions & 2 deletions test/specs/core.helpers.tests.js
Expand Up @@ -128,8 +128,9 @@ describe('Core helper tests', function() {
},
position: 'right',
scaleLabel: {
labelString: '',
display: false,
labelString: '',
lineHeight: 1.5
},
ticks: {
beginAtZero: false,
Expand Down Expand Up @@ -168,8 +169,9 @@ describe('Core helper tests', function() {
},
position: 'left',
scaleLabel: {
labelString: '',
display: false,
labelString: '',
lineHeight: 1.5
},
ticks: {
beginAtZero: false,
Expand Down
27 changes: 27 additions & 0 deletions test/specs/helpers.options.tests.js
@@ -0,0 +1,27 @@
'use strict';

describe('Chart.helpers.options', function() {
var options = Chart.helpers.options;

describe('toLineHeight', function() {
it ('should support keyword values', function() {
expect(options.toLineHeight('normal', 16)).toBe(16 * 1.2);
});
it ('should support unitless values', function() {
expect(options.toLineHeight(1.4, 16)).toBe(16 * 1.4);
expect(options.toLineHeight('1.4', 16)).toBe(16 * 1.4);
});
it ('should support length values', function() {
expect(options.toLineHeight('42px', 16)).toBe(42);
expect(options.toLineHeight('1.4em', 16)).toBe(16 * 1.4);
});
it ('should support percentage values', function() {
expect(options.toLineHeight('140%', 16)).toBe(16 * 1.4);
});
it ('should fallback to default (1.2) for invalid values', function() {
expect(options.toLineHeight(null, 16)).toBe(16 * 1.2);
expect(options.toLineHeight(undefined, 16)).toBe(16 * 1.2);
expect(options.toLineHeight('foobar', 16)).toBe(16 * 1.2);
});
});
});
15 changes: 8 additions & 7 deletions test/specs/plugin.title.tests.js
Expand Up @@ -13,6 +13,7 @@ describe('Title block tests', function() {
fullWidth: true,
weight: 2000,
fontStyle: 'bold',
lineHeight: 1.2,
padding: 10,
text: ''
});
Expand Down Expand Up @@ -43,7 +44,7 @@ describe('Title block tests', function() {

expect(minSize).toEqual({
width: 400,
height: 32
height: 34.4
});
});

Expand Down Expand Up @@ -72,7 +73,7 @@ describe('Title block tests', function() {
minSize = title.update(200, 400);

expect(minSize).toEqual({
width: 32,
width: 34.4,
height: 400
});
});
Expand All @@ -84,7 +85,7 @@ describe('Title block tests', function() {
options.text = ['line1', 'line2'];
options.position = 'left';
options.display = true;
options.lineHeight = 15;
options.lineHeight = 1.5;

var title = new Chart.Title({
chart: chart,
Expand All @@ -94,7 +95,7 @@ describe('Title block tests', function() {
var minSize = title.update(200, 400);

expect(minSize).toEqual({
width: 50,
width: 56,
height: 400
});
});
Expand Down Expand Up @@ -135,7 +136,7 @@ describe('Title block tests', function() {
args: []
}, {
name: 'translate',
args: [300, 66]
args: [300, 67.2]
}, {
name: 'rotate',
args: [0]
Expand Down Expand Up @@ -185,7 +186,7 @@ describe('Title block tests', function() {
args: []
}, {
name: 'translate',
args: [106, 250]
args: [117.2, 250]
}, {
name: 'rotate',
args: [-0.5 * Math.PI]
Expand Down Expand Up @@ -218,7 +219,7 @@ describe('Title block tests', function() {
args: []
}, {
name: 'translate',
args: [126, 250]
args: [117.2, 250]
}, {
name: 'rotate',
args: [0.5 * Math.PI]
Expand Down
3 changes: 2 additions & 1 deletion test/specs/scale.category.tests.js
Expand Up @@ -30,8 +30,9 @@ describe('Category scale tests', function() {
},
position: 'bottom',
scaleLabel: {
display: false,
labelString: '',
display: false
lineHeight: 1.5
},
ticks: {
beginAtZero: false,
Expand Down
6 changes: 4 additions & 2 deletions test/specs/scale.linear.tests.js
Expand Up @@ -28,8 +28,9 @@ describe('Linear Scale', function() {
},
position: 'left',
scaleLabel: {
labelString: '',
display: false,
labelString: '',
lineHeight: 1.5
},
ticks: {
beginAtZero: false,
Expand Down Expand Up @@ -820,7 +821,8 @@ describe('Linear Scale', function() {
drawBorder: false
},
scaleLabel: {
display: false
display: false,
lineHeight: 1.5
},
ticks: {
display: false,
Expand Down
3 changes: 2 additions & 1 deletion test/specs/scale.logarithmic.tests.js
Expand Up @@ -27,8 +27,9 @@ describe('Logarithmic Scale tests', function() {
},
position: 'left',
scaleLabel: {
labelString: '',
display: false,
labelString: '',
lineHeight: 1.5
},
ticks: {
beginAtZero: false,
Expand Down
3 changes: 2 additions & 1 deletion test/specs/scale.radialLinear.tests.js
Expand Up @@ -40,8 +40,9 @@ describe('Test the radial linear scale', function() {
},
position: 'chartArea',
scaleLabel: {
labelString: '',
display: false,
labelString: '',
lineHeight: 1.5
},
ticks: {
backdropColor: 'rgba(255,255,255,0.75)',
Expand Down
3 changes: 2 additions & 1 deletion test/specs/scale.time.tests.js
Expand Up @@ -75,8 +75,9 @@ describe('Time scale tests', function() {
},
position: 'bottom',
scaleLabel: {
display: false,
labelString: '',
display: false
lineHeight: 1.5
},
ticks: {
beginAtZero: false,
Expand Down

0 comments on commit 9dea44a

Please sign in to comment.