Skip to content

Commit 23cf379

Browse files
stockiNailkurkle
andauthored
Use font.lineHeight instead of font.size for labelling in line annotation (#475)
* Fixes #474 * removes 1.5 adjustment fo textbaseline set to top * Update src/types/line.js Co-authored-by: Jukka Kurkela <[email protected]> * uses 'middle' instead of 'top' to textBaseline option Co-authored-by: Jukka Kurkela <[email protected]>
1 parent 0bf82c5 commit 23cf379

File tree

7 files changed

+32
-36
lines changed

7 files changed

+32
-36
lines changed

src/types/line.js

Lines changed: 32 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {Element} from 'chart.js';
2-
import {addRoundedRectPath, isArray, toFontString, toRadians, toTRBLCorners, valueOrDefault} from 'chart.js/helpers';
2+
import {addRoundedRectPath, isArray, toFont, toRadians, toTRBLCorners, valueOrDefault} from 'chart.js/helpers';
33
import {clamp, clampAll, scaleValue, rotated} from '../helpers';
44

55
const PI = Math.PI;
@@ -181,8 +181,8 @@ LineAnnotation.defaults = {
181181
family: undefined,
182182
lineHeight: undefined,
183183
size: undefined,
184-
style: 'bold',
185-
weight: undefined
184+
style: undefined,
185+
weight: 'bold'
186186
},
187187
color: '#fff',
188188
xPadding: 6,
@@ -192,6 +192,8 @@ LineAnnotation.defaults = {
192192
xAdjust: 0,
193193
yAdjust: 0,
194194
textAlign: 'center',
195+
width: undefined,
196+
height: undefined,
195197
enabled: false,
196198
content: null
197199
},
@@ -219,10 +221,11 @@ function calculateAutoRotation(line) {
219221

220222
function drawLabel(ctx, line, chartArea) {
221223
const label = line.options.label;
224+
const {borderWidth, xPadding, yPadding, content} = label;
225+
const font = toFont(label.font);
226+
ctx.font = font.string;
222227

223-
ctx.font = toFontString(label.font);
224-
225-
const {width, height} = measureLabel(ctx, label);
228+
const {width, height} = measureLabel(ctx, label, font);
226229
const rect = line.labelRect = calculateLabelPosition(line, width, height, chartArea);
227230

228231
ctx.translate(rect.x, rect.y);
@@ -244,27 +247,17 @@ function drawLabel(ctx, line, chartArea) {
244247
}
245248

246249
ctx.fillStyle = label.color;
247-
if (isArray(label.content)) {
248-
ctx.textAlign = label.textAlign;
249-
const x = calculateLabelXAlignment(label, width);
250-
let textYPosition = -(height / 2) + label.yPadding;
251-
for (let i = 0; i < label.content.length; i++) {
252-
ctx.textBaseline = 'top';
253-
ctx.fillText(
254-
label.content[i],
255-
x,
256-
textYPosition
257-
);
258-
textYPosition += label.font.size + label.yPadding;
259-
}
260-
} else if (label.content instanceof Image) {
261-
const x = -(width / 2) + label.xPadding;
262-
const y = -(height / 2) + label.yPadding;
263-
ctx.drawImage(label.content, x, y, width - (2 * label.xPadding), height - (2 * label.yPadding));
250+
if (content instanceof Image) {
251+
const x = -(width / 2) + xPadding + borderWidth / 2;
252+
const y = -(height / 2) + yPadding + borderWidth / 2;
253+
ctx.drawImage(content, x, y, width - (2 * xPadding) - borderWidth, height - (2 * yPadding) - borderWidth);
264254
} else {
265-
ctx.textAlign = 'center';
255+
const labels = isArray(content) ? content : [content];
256+
const x = calculateLabelXAlignment(label, width);
257+
const y = -(labels.length - 1) * font.lineHeight / 2;
266258
ctx.textBaseline = 'middle';
267-
ctx.fillText(label.content, 0, 0);
259+
ctx.textAlign = label.textAlign;
260+
labels.forEach((l, i) => ctx.fillText(l, x, y + (i * font.lineHeight)));
268261
}
269262
}
270263

@@ -281,11 +274,11 @@ function setBorderStyle(ctx, options) {
281274
}
282275

283276
function calculateLabelXAlignment(label, width) {
284-
const {textAlign, xPadding} = label;
277+
const {textAlign, xPadding, borderWidth} = label;
285278
if (textAlign === 'start') {
286-
return -(width / 2) + xPadding;
279+
return -(width / 2) + xPadding + borderWidth / 2;
287280
} else if (textAlign === 'end') {
288-
return +(width / 2) - xPadding;
281+
return +(width / 2) - xPadding - borderWidth / 2;
289282
}
290283
return 0;
291284
}
@@ -300,29 +293,32 @@ function getImageSize(size, value) {
300293
}
301294

302295
const widthCache = new Map();
303-
function measureLabel(ctx, label) {
296+
function measureLabel(ctx, label, font) {
304297
const content = label.content;
298+
const borderWidth = label.borderWidth;
299+
305300
if (content instanceof Image) {
306301
return {
307-
width: getImageSize(content.width, label.width) + 2 * label.xPadding,
308-
height: getImageSize(content.height, label.height) + 2 * label.yPadding
302+
width: getImageSize(content.width, label.width) + 2 * label.xPadding + borderWidth,
303+
height: getImageSize(content.height, label.height) + 2 * label.yPadding + borderWidth
309304
};
310305
}
311306
const lines = isArray(content) ? content : [content];
312307
const count = lines.length;
313308
let width = 0;
314309
for (let i = 0; i < count; i++) {
315310
const text = lines[i];
316-
if (!widthCache.has(text)) {
317-
widthCache.set(text, ctx.measureText(text).width);
311+
const key = font.string + '-' + text;
312+
if (!widthCache.has(key)) {
313+
widthCache.set(key, ctx.measureText(text).width);
318314
}
319-
width = Math.max(width, widthCache.get(text));
315+
width = Math.max(width, widthCache.get(key));
320316
}
321-
width += 2 * label.xPadding;
317+
width += 2 * label.xPadding + borderWidth;
322318

323319
return {
324320
width,
325-
height: count * label.font.size + ((count + 1) * label.yPadding)
321+
height: count * font.lineHeight + label.yPadding * 2 + borderWidth
326322
};
327323
}
328324

206 Bytes
Loading
1.18 KB
Loading
945 Bytes
Loading

test/fixtures/line/position.png

577 Bytes
Loading

test/fixtures/line/rotation.png

945 Bytes
Loading
945 Bytes
Loading

0 commit comments

Comments
 (0)