mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
Use font lineHeight for tooltip alignment (#8631)
* Use font lineHeight for tooltip alignment * Remove toFontString usage from tooltip
This commit is contained in:
parent
2bff4c1640
commit
96f6b42c57
@ -1,10 +1,10 @@
|
||||
import Animations from '../core/core.animations';
|
||||
import Element from '../core/core.element';
|
||||
import {each, noop, isNullOrUndef, isArray, _elementsEqual} from '../helpers/helpers.core';
|
||||
import {toPadding} from '../helpers/helpers.options';
|
||||
import {toFont, toPadding} from '../helpers/helpers.options';
|
||||
import {getRtlAdapter, overrideTextDirection, restoreTextDirection} from '../helpers/helpers.rtl';
|
||||
import {distanceBetweenPoints} from '../helpers/helpers.math';
|
||||
import {drawPoint, toFontString} from '../helpers';
|
||||
import {drawPoint} from '../helpers';
|
||||
|
||||
/**
|
||||
* @typedef { import("../platform/platform.base").ChartEvent } ChartEvent
|
||||
@ -139,7 +139,10 @@ function createTooltipItem(chart, item) {
|
||||
function getTooltipSize(tooltip, options) {
|
||||
const ctx = tooltip._chart.ctx;
|
||||
const {body, footer, title} = tooltip;
|
||||
const {bodyFont, footerFont, titleFont, boxWidth, boxHeight} = options;
|
||||
const {boxWidth, boxHeight} = options;
|
||||
const bodyFont = toFont(options.bodyFont);
|
||||
const titleFont = toFont(options.titleFont);
|
||||
const footerFont = toFont(options.footerFont);
|
||||
const titleLineCount = title.length;
|
||||
const footerLineCount = footer.length;
|
||||
const bodyLineItemCount = body.length;
|
||||
@ -153,20 +156,20 @@ function getTooltipSize(tooltip, options) {
|
||||
combinedBodyLength += tooltip.beforeBody.length + tooltip.afterBody.length;
|
||||
|
||||
if (titleLineCount) {
|
||||
height += titleLineCount * titleFont.size
|
||||
height += titleLineCount * titleFont.lineHeight
|
||||
+ (titleLineCount - 1) * options.titleSpacing
|
||||
+ options.titleMarginBottom;
|
||||
}
|
||||
if (combinedBodyLength) {
|
||||
// Body lines may include some extra height depending on boxHeight
|
||||
const bodyLineHeight = options.displayColors ? Math.max(boxHeight, bodyFont.size) : bodyFont.size;
|
||||
const bodyLineHeight = options.displayColors ? Math.max(boxHeight, bodyFont.lineHeight) : bodyFont.lineHeight;
|
||||
height += bodyLineItemCount * bodyLineHeight
|
||||
+ (combinedBodyLength - bodyLineItemCount) * bodyFont.size
|
||||
+ (combinedBodyLength - bodyLineItemCount) * bodyFont.lineHeight
|
||||
+ (combinedBodyLength - 1) * options.bodySpacing;
|
||||
}
|
||||
if (footerLineCount) {
|
||||
height += options.footerMarginTop
|
||||
+ footerLineCount * footerFont.size
|
||||
+ footerLineCount * footerFont.lineHeight
|
||||
+ (footerLineCount - 1) * options.footerSpacing;
|
||||
}
|
||||
|
||||
@ -178,11 +181,11 @@ function getTooltipSize(tooltip, options) {
|
||||
|
||||
ctx.save();
|
||||
|
||||
ctx.font = toFontString(titleFont);
|
||||
ctx.font = titleFont.string;
|
||||
each(tooltip.title, maxLineWidth);
|
||||
|
||||
// Body width
|
||||
ctx.font = toFontString(bodyFont);
|
||||
ctx.font = bodyFont.string;
|
||||
each(tooltip.beforeBody.concat(tooltip.afterBody), maxLineWidth);
|
||||
|
||||
// Body lines may include some extra width due to the color box
|
||||
@ -197,7 +200,7 @@ function getTooltipSize(tooltip, options) {
|
||||
widthPadding = 0;
|
||||
|
||||
// Footer width
|
||||
ctx.font = toFontString(footerFont);
|
||||
ctx.font = footerFont.string;
|
||||
each(tooltip.footer, maxLineWidth);
|
||||
|
||||
ctx.restore();
|
||||
@ -652,15 +655,15 @@ export class Tooltip extends Element {
|
||||
ctx.textAlign = rtlHelper.textAlign(options.titleAlign);
|
||||
ctx.textBaseline = 'middle';
|
||||
|
||||
titleFont = options.titleFont;
|
||||
titleFont = toFont(options.titleFont);
|
||||
titleSpacing = options.titleSpacing;
|
||||
|
||||
ctx.fillStyle = options.titleColor;
|
||||
ctx.font = toFontString(titleFont);
|
||||
ctx.font = titleFont.string;
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
ctx.fillText(title[i], rtlHelper.x(pt.x), pt.y + titleFont.size / 2);
|
||||
pt.y += titleFont.size + titleSpacing; // Line Height and spacing
|
||||
ctx.fillText(title[i], rtlHelper.x(pt.x), pt.y + titleFont.lineHeight / 2);
|
||||
pt.y += titleFont.lineHeight + titleSpacing; // Line Height and spacing
|
||||
|
||||
if (i + 1 === length) {
|
||||
pt.y += options.titleMarginBottom - titleSpacing; // If Last, add margin, remove spacing
|
||||
@ -676,10 +679,11 @@ export class Tooltip extends Element {
|
||||
const me = this;
|
||||
const labelColors = me.labelColors[i];
|
||||
const labelPointStyle = me.labelPointStyles[i];
|
||||
const {boxHeight, boxWidth, bodyFont} = options;
|
||||
const {boxHeight, boxWidth} = options;
|
||||
const bodyFont = toFont(options.bodyFont);
|
||||
const colorX = getAlignedX(me, 'left', options);
|
||||
const rtlColorX = rtlHelper.x(colorX);
|
||||
const yOffSet = boxHeight < bodyFont.size ? (bodyFont.size - boxHeight) / 2 : 0;
|
||||
const yOffSet = boxHeight < bodyFont.lineHeight ? (bodyFont.lineHeight - boxHeight) / 2 : 0;
|
||||
const colorY = pt.y + yOffSet;
|
||||
|
||||
if (options.usePointStyle) {
|
||||
@ -725,8 +729,9 @@ export class Tooltip extends Element {
|
||||
drawBody(pt, ctx, options) {
|
||||
const me = this;
|
||||
const {body} = me;
|
||||
const {bodyFont, bodySpacing, bodyAlign, displayColors, boxHeight, boxWidth} = options;
|
||||
let bodyLineHeight = bodyFont.size;
|
||||
const {bodySpacing, bodyAlign, displayColors, boxHeight, boxWidth} = options;
|
||||
const bodyFont = toFont(options.bodyFont);
|
||||
let bodyLineHeight = bodyFont.lineHeight;
|
||||
let xLinePadding = 0;
|
||||
|
||||
const rtlHelper = getRtlAdapter(options.rtl, me.x, me.width);
|
||||
@ -741,7 +746,7 @@ export class Tooltip extends Element {
|
||||
|
||||
ctx.textAlign = bodyAlign;
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.font = toFontString(bodyFont);
|
||||
ctx.font = bodyFont.string;
|
||||
|
||||
pt.x = getAlignedX(me, bodyAlignForCalculation, options);
|
||||
|
||||
@ -765,13 +770,13 @@ export class Tooltip extends Element {
|
||||
// Draw Legend-like boxes if needed
|
||||
if (displayColors && lines.length) {
|
||||
me._drawColorBox(ctx, pt, i, rtlHelper, options);
|
||||
bodyLineHeight = Math.max(bodyFont.size, boxHeight);
|
||||
bodyLineHeight = Math.max(bodyFont.lineHeight, boxHeight);
|
||||
}
|
||||
|
||||
for (j = 0, jlen = lines.length; j < jlen; ++j) {
|
||||
fillLineOfText(lines[j]);
|
||||
// Reset for any lines that don't include colorbox
|
||||
bodyLineHeight = bodyFont.size;
|
||||
bodyLineHeight = bodyFont.lineHeight;
|
||||
}
|
||||
|
||||
each(bodyItem.after, fillLineOfText);
|
||||
@ -779,7 +784,7 @@ export class Tooltip extends Element {
|
||||
|
||||
// Reset back to 0 for after body
|
||||
xLinePadding = 0;
|
||||
bodyLineHeight = bodyFont.size;
|
||||
bodyLineHeight = bodyFont.lineHeight;
|
||||
|
||||
// After body lines
|
||||
each(me.afterBody, fillLineOfText);
|
||||
@ -801,14 +806,14 @@ export class Tooltip extends Element {
|
||||
ctx.textAlign = rtlHelper.textAlign(options.footerAlign);
|
||||
ctx.textBaseline = 'middle';
|
||||
|
||||
footerFont = options.footerFont;
|
||||
footerFont = toFont(options.footerFont);
|
||||
|
||||
ctx.fillStyle = options.footerColor;
|
||||
ctx.font = toFontString(footerFont);
|
||||
ctx.font = footerFont.string;
|
||||
|
||||
for (i = 0; i < length; ++i) {
|
||||
ctx.fillText(footer[i], rtlHelper.x(pt.x), pt.y + footerFont.size / 2);
|
||||
pt.y += footerFont.size + options.footerSpacing;
|
||||
ctx.fillText(footer[i], rtlHelper.x(pt.x), pt.y + footerFont.lineHeight / 2);
|
||||
pt.y += footerFont.lineHeight + options.footerSpacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,8 +163,8 @@ describe('Plugin.Tooltip', function() {
|
||||
}]
|
||||
}));
|
||||
|
||||
expect(tooltip.x).toBeCloseToPixel(267);
|
||||
expect(tooltip.y).toBeCloseToPixel(155);
|
||||
expect(tooltip.x).toBeCloseToPixel(266);
|
||||
expect(tooltip.y).toBeCloseToPixel(150);
|
||||
});
|
||||
|
||||
it('Should only display if intersecting if intersect is set', async function() {
|
||||
@ -311,7 +311,7 @@ describe('Plugin.Tooltip', function() {
|
||||
}]);
|
||||
|
||||
expect(tooltip.x).toBeCloseToPixel(267);
|
||||
expect(tooltip.y).toBeCloseToPixel(312);
|
||||
expect(tooltip.y).toBeCloseToPixel(308);
|
||||
});
|
||||
|
||||
it('Should display information from user callbacks', async function() {
|
||||
@ -475,7 +475,7 @@ describe('Plugin.Tooltip', function() {
|
||||
}));
|
||||
|
||||
expect(tooltip.x).toBeCloseToPixel(267);
|
||||
expect(tooltip.y).toBeCloseToPixel(75);
|
||||
expect(tooltip.y).toBeCloseToPixel(58);
|
||||
});
|
||||
|
||||
it('Should provide context object to user callbacks', async function() {
|
||||
@ -581,7 +581,7 @@ describe('Plugin.Tooltip', function() {
|
||||
}));
|
||||
|
||||
expect(tooltip.x).toBeCloseToPixel(267);
|
||||
expect(tooltip.y).toBeCloseToPixel(155);
|
||||
expect(tooltip.y).toBeCloseToPixel(150);
|
||||
});
|
||||
|
||||
it('Should allow reversing items', async function() {
|
||||
@ -649,7 +649,7 @@ describe('Plugin.Tooltip', function() {
|
||||
}));
|
||||
|
||||
expect(tooltip.x).toBeCloseToPixel(267);
|
||||
expect(tooltip.y).toBeCloseToPixel(155);
|
||||
expect(tooltip.y).toBeCloseToPixel(150);
|
||||
});
|
||||
|
||||
it('Should follow dataset order', async function() {
|
||||
@ -718,7 +718,7 @@ describe('Plugin.Tooltip', function() {
|
||||
}));
|
||||
|
||||
expect(tooltip.x).toBeCloseToPixel(267);
|
||||
expect(tooltip.y).toBeCloseToPixel(155);
|
||||
expect(tooltip.y).toBeCloseToPixel(150);
|
||||
});
|
||||
|
||||
it('should filter items from the tooltip using the callback', async function() {
|
||||
@ -1393,18 +1393,18 @@ describe('Plugin.Tooltip', function() {
|
||||
{name: 'setTextBaseline', args: ['middle']},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'setFont', args: ["bold 12px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"]},
|
||||
{name: 'fillText', args: ['title', 105, 111]},
|
||||
{name: 'fillText', args: ['title', 105, 112.2]},
|
||||
{name: 'setTextAlign', args: ['left']},
|
||||
{name: 'setTextBaseline', args: ['middle']},
|
||||
{name: 'setFont', args: ["normal 12px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"]},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'fillText', args: ['label', 105, 129]},
|
||||
{name: 'fillText', args: ['label', 105, 132.6]},
|
||||
{name: 'setTextAlign', args: ['left']},
|
||||
{name: 'setTextBaseline', args: ['middle']},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'setFont', args: ["bold 12px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"]},
|
||||
{name: 'fillText', args: ['footer', 105, 147]},
|
||||
{name: 'fillText', args: ['footer', 105, 153]},
|
||||
{name: 'restore', args: []}
|
||||
]));
|
||||
});
|
||||
@ -1419,18 +1419,18 @@ describe('Plugin.Tooltip', function() {
|
||||
{name: 'setTextBaseline', args: ['middle']},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'setFont', args: ["bold 12px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"]},
|
||||
{name: 'fillText', args: ['title', 195, 111]},
|
||||
{name: 'fillText', args: ['title', 195, 112.2]},
|
||||
{name: 'setTextAlign', args: ['right']},
|
||||
{name: 'setTextBaseline', args: ['middle']},
|
||||
{name: 'setFont', args: ["normal 12px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"]},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'fillText', args: ['label', 195, 129]},
|
||||
{name: 'fillText', args: ['label', 195, 132.6]},
|
||||
{name: 'setTextAlign', args: ['right']},
|
||||
{name: 'setTextBaseline', args: ['middle']},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'setFont', args: ["bold 12px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"]},
|
||||
{name: 'fillText', args: ['footer', 195, 147]},
|
||||
{name: 'fillText', args: ['footer', 195, 153]},
|
||||
{name: 'restore', args: []}
|
||||
]));
|
||||
});
|
||||
@ -1445,18 +1445,18 @@ describe('Plugin.Tooltip', function() {
|
||||
{name: 'setTextBaseline', args: ['middle']},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'setFont', args: ["bold 12px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"]},
|
||||
{name: 'fillText', args: ['title', 150, 111]},
|
||||
{name: 'fillText', args: ['title', 150, 112.2]},
|
||||
{name: 'setTextAlign', args: ['center']},
|
||||
{name: 'setTextBaseline', args: ['middle']},
|
||||
{name: 'setFont', args: ["normal 12px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"]},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'fillText', args: ['label', 150, 129]},
|
||||
{name: 'fillText', args: ['label', 150, 132.6]},
|
||||
{name: 'setTextAlign', args: ['center']},
|
||||
{name: 'setTextBaseline', args: ['middle']},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'setFont', args: ["bold 12px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"]},
|
||||
{name: 'fillText', args: ['footer', 150, 147]},
|
||||
{name: 'fillText', args: ['footer', 150, 153]},
|
||||
{name: 'restore', args: []}
|
||||
]));
|
||||
});
|
||||
@ -1471,18 +1471,18 @@ describe('Plugin.Tooltip', function() {
|
||||
{name: 'setTextBaseline', args: ['middle']},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'setFont', args: ["bold 12px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"]},
|
||||
{name: 'fillText', args: ['title', 195, 111]},
|
||||
{name: 'fillText', args: ['title', 195, 112.2]},
|
||||
{name: 'setTextAlign', args: ['center']},
|
||||
{name: 'setTextBaseline', args: ['middle']},
|
||||
{name: 'setFont', args: ["normal 12px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"]},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'fillText', args: ['label', 150, 129]},
|
||||
{name: 'fillText', args: ['label', 150, 132.6]},
|
||||
{name: 'setTextAlign', args: ['left']},
|
||||
{name: 'setTextBaseline', args: ['middle']},
|
||||
{name: 'setFillStyle', args: ['#fff']},
|
||||
{name: 'setFont', args: ["bold 12px 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"]},
|
||||
{name: 'fillText', args: ['footer', 105, 147]},
|
||||
{name: 'fillText', args: ['footer', 105, 153]},
|
||||
{name: 'restore', args: []}
|
||||
]));
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user