]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Implement scale label padding (#4646) 4706/head
authorandig <cpuidle@gmx.de>
Sun, 10 Sep 2017 17:15:47 +0000 (19:15 +0200)
committerEvert Timberg <evert.timberg+github@gmail.com>
Sun, 10 Sep 2017 17:15:47 +0000 (13:15 -0400)
docs/axes/labelling.md
src/core/core.scale.js
test/fixtures/core.scale/label-offset-vertical-axes.png
test/specs/core.helpers.tests.js
test/specs/core.scale.tests.js
test/specs/core.tooltip.tests.js
test/specs/scale.category.tests.js
test/specs/scale.linear.tests.js
test/specs/scale.logarithmic.tests.js
test/specs/scale.radialLinear.tests.js
test/specs/scale.time.tests.js

index 22fc2600463bcd35ac01262ffca7a8b96ad39b95..aec8d990ff48d45fe407dd434fb341b3656ab240 100644 (file)
@@ -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
 
index bc4d1ec9c7bdbef9105c5e1a289139e1e621eab8..f48b67a5ec19ac5e8c50cad16c6e76a94953b89b 100644 (file)
@@ -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;
                                }
index 2f6b18c8c23939f2b79177a937ba2458298f826b..05785b8bc597181170ffe7bae4e472f35f8a0620 100644 (file)
Binary files a/test/fixtures/core.scale/label-offset-vertical-axes.png and b/test/fixtures/core.scale/label-offset-vertical-axes.png differ
index 1b5edb89edf945522e2679b51c76b618df552b5e..dc865fb01b2062ff930f33d164e3702f637fb14f 100644 (file)
@@ -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,
index 58e5a33faeb06733cbb85316786c772caf305365..dc2da042aca3310576b2cfe99aa1ea6c25d785ec 100644 (file)
@@ -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
+                       }
+               });
+       });
 });
index b1896da3338eb85660030b255a0daaabb5b6a9aa..73d943bd853394c8b246eacc307b58b52d8af434 100755 (executable)
@@ -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);
        });
 
index 8d8d32cd424d94bee33f645acd018a774eacbdec..1665235ae8d636c2206c678a1780808ba2115f5a 100644 (file)
@@ -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);
        });
 
index ed6f9c1f96ed8ecbb6203e5120d11a3aeb0d5a92..60dd07698c0d0ec68f4bed5b6f765f43ddaf2f97 100644 (file)
@@ -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() {
index 98d0fbf09c4cb0948f9ee17890fe3b40475ace67..9640b1d3d6281782fde04ec51d552d49acd1bb95 100644 (file)
@@ -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);
index 70c75f02ad7249ff540f18842d055dfeb5e38bbf..707ce0b7c52c3a983f77cae2638eb1a2b4cda073 100644 (file)
@@ -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,
index ac79368ec51050ef24b227125e00ee1a52a8b5b5..98dd774b6bee30b576903e2ebef6cdc286ecd9d6 100755 (executable)
@@ -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: {