From: Jukka Kurkela Date: Tue, 9 Mar 2021 13:35:43 +0000 (+0200) Subject: Scale: refactor drawTitle, add tests (#8598) X-Git-Tag: v3.0.0-beta.14~37 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f7ebedc367c3e6dabd7b4a65a26706620d2df430;p=thirdparty%2FChart.js.git Scale: refactor drawTitle, add tests (#8598) * Scale: refactor drawTitle, add tests * CC, lint * update --- diff --git a/src/core/core.scale.js b/src/core/core.scale.js index ca7b278dd..684916e7f 100644 --- a/src/core/core.scale.js +++ b/src/core/core.scale.js @@ -2,10 +2,14 @@ import defaults from './core.defaults'; import Element from './core.element'; import {_alignPixel, _measureText, renderText, clipArea, unclipArea} from '../helpers/helpers.canvas'; import {callback as call, each, finiteOrDefault, isArray, isFinite, isNullOrUndef, isObject, valueOrDefault} from '../helpers/helpers.core'; -import {_factorize, toDegrees, toRadians, _int16Range, HALF_PI, _limitValue} from '../helpers/helpers.math'; +import {_factorize, toDegrees, toRadians, _int16Range, _limitValue, HALF_PI} from '../helpers/helpers.math'; +import {_alignStartEnd, _toLeftRightCenter} from '../helpers/helpers.extras'; import {toFont, toPadding} from '../helpers/helpers.options'; import Ticks from './core.ticks'; +const reverseAlign = (align) => align === 'left' ? 'right' : align === 'right' ? 'left' : align; +const offsetFromEdge = (scale, edge, offset) => edge === 'top' || edge === 'left' ? scale[edge] + offset : scale[edge] - offset; + /** * @typedef { import("./core.controller").default } Chart * @typedef {{value:number | string, label?:string, major?:boolean, $context?:any}} Tick @@ -317,6 +321,31 @@ function createTickContext(parent, index, tick) { }); } +function titleAlign(align, position, reverse) { + let ret = _toLeftRightCenter(align); + if ((reverse && position !== 'right') || (!reverse && position === 'right')) { + ret = reverseAlign(ret); + } + return ret; +} + +function titleArgs(scale, offset, position, align) { + const {top, left, bottom, right} = scale; + let rotation = 0; + let maxWidth, titleX, titleY; + + if (scale.isHorizontal()) { + titleX = _alignStartEnd(align, left, right); + titleY = offsetFromEdge(scale, position, offset); + maxWidth = right - left; + } else { + titleX = offsetFromEdge(scale, position, offset); + titleY = _alignStartEnd(align, bottom, top); + rotation = position === 'left' ? -HALF_PI : HALF_PI; + } + return {titleX, titleY, maxWidth, rotation}; +} + export default class Scale extends Element { // eslint-disable-next-line max-statements @@ -1661,69 +1690,34 @@ export default class Scale extends Element { /** * @protected */ - drawTitle(chartArea) { // eslint-disable-line no-unused-vars - const me = this; - const ctx = me.ctx; - const options = me.options; - const title = options.title; + drawTitle() { + const {ctx, options: {position, title, reverse}} = this; if (!title.display) { return; } - const titleFont = toFont(title.font); - const titlePadding = toPadding(title.padding); - const halfLineHeight = titleFont.lineHeight / 2; - const titleAlign = title.align; - const position = options.position; - const isReverse = me.options.reverse; - let rotation = 0; - /** @type CanvasTextAlign */ - let textAlign; - let titleX, titleY; + const font = toFont(title.font); + const padding = toPadding(title.padding); + const align = title.align; + let offset = font.lineHeight / 2; - if (me.isHorizontal()) { - switch (titleAlign) { - case 'start': - titleX = me.left + (isReverse ? me.width : 0); - textAlign = isReverse ? 'right' : 'left'; - break; - case 'end': - titleX = me.left + (isReverse ? 0 : me.width); - textAlign = isReverse ? 'left' : 'right'; - break; - default: - titleX = me.left + me.width / 2; - textAlign = 'center'; + if (position === 'bottom') { + offset += padding.bottom; + if (isArray(title.text)) { + offset += font.lineHeight * (title.text.length - 1); } - titleY = position === 'top' - ? me.top + halfLineHeight + titlePadding.top - : me.bottom - halfLineHeight - titlePadding.bottom; } else { - const isLeft = position === 'left'; - titleX = isLeft - ? me.left + halfLineHeight + titlePadding.top - : me.right - halfLineHeight - titlePadding.top; - switch (titleAlign) { - case 'start': - titleY = me.top + (isReverse ? 0 : me.height); - textAlign = isReverse === isLeft ? 'right' : 'left'; - break; - case 'end': - titleY = me.top + (isReverse ? me.height : 0); - textAlign = isReverse === isLeft ? 'left' : 'right'; - break; - default: - titleY = me.top + me.height / 2; - textAlign = 'center'; - } - rotation = isLeft ? -HALF_PI : HALF_PI; + offset += padding.top; } - renderText(ctx, title.text, 0, 0, titleFont, { + const {titleX, titleY, maxWidth, rotation} = titleArgs(this, offset, position, align); + + renderText(ctx, title.text, 0, 0, font, { color: title.color, + maxWidth, rotation, - textAlign, + textAlign: titleAlign(align, position, reverse), textBaseline: 'middle', translation: [titleX, titleY], }); diff --git a/test/fixtures/core.scale/title-multi-line.js b/test/fixtures/core.scale/title-multi-line.js deleted file mode 100644 index d116254f8..000000000 --- a/test/fixtures/core.scale/title-multi-line.js +++ /dev/null @@ -1,32 +0,0 @@ -module.exports = { - config: { - type: 'line', - data: { - datasets: [{ - data: [1, -1, 3], - }], - labels: ['Label1', 'Label2', 'Label3'] - }, - options: { - scales: { - y: { - title: { - display: true, - text: [ - 'Line 1', - 'Line 2', - 'Line 3', - ] - } - } - } - } - }, - options: { - spriteText: true, - canvas: { - height: 256, - width: 512 - } - } -}; diff --git a/test/fixtures/core.scale/title-multi-line.png b/test/fixtures/core.scale/title-multi-line.png deleted file mode 100644 index 291bb2865..000000000 Binary files a/test/fixtures/core.scale/title-multi-line.png and /dev/null differ diff --git a/test/fixtures/core.scale/title/align-end.js b/test/fixtures/core.scale/title/align-end.js new file mode 100644 index 000000000..81059cf94 --- /dev/null +++ b/test/fixtures/core.scale/title/align-end.js @@ -0,0 +1,77 @@ +module.exports = { + config: { + type: 'line', + options: { + events: [], + scales: { + top: { + type: 'linear', + position: 'top', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'end', + text: 'top' + } + }, + left: { + type: 'linear', + position: 'left', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'end', + text: 'left' + } + }, + bottom: { + type: 'linear', + position: 'bottom', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'end', + text: 'bottom' + } + }, + right: { + type: 'linear', + position: 'right', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'end', + text: 'right' + } + }, + } + } + }, + options: { + spriteText: true, + canvas: { + height: 256, + width: 256 + }, + } +}; diff --git a/test/fixtures/core.scale/title/align-end.png b/test/fixtures/core.scale/title/align-end.png new file mode 100644 index 000000000..f52a7bf73 Binary files /dev/null and b/test/fixtures/core.scale/title/align-end.png differ diff --git a/test/fixtures/core.scale/title/align-start.js b/test/fixtures/core.scale/title/align-start.js new file mode 100644 index 000000000..385f1725e --- /dev/null +++ b/test/fixtures/core.scale/title/align-start.js @@ -0,0 +1,77 @@ +module.exports = { + config: { + type: 'line', + options: { + events: [], + scales: { + top: { + type: 'linear', + position: 'top', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'start', + text: 'top' + } + }, + left: { + type: 'linear', + position: 'left', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'start', + text: 'left' + } + }, + bottom: { + type: 'linear', + position: 'bottom', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'start', + text: 'bottom' + } + }, + right: { + type: 'linear', + position: 'right', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'start', + text: 'right' + } + }, + } + } + }, + options: { + spriteText: true, + canvas: { + height: 256, + width: 256 + }, + } +}; diff --git a/test/fixtures/core.scale/title/align-start.png b/test/fixtures/core.scale/title/align-start.png new file mode 100644 index 000000000..7a1317ec1 Binary files /dev/null and b/test/fixtures/core.scale/title/align-start.png differ diff --git a/test/fixtures/core.scale/title/default.js b/test/fixtures/core.scale/title/default.js new file mode 100644 index 000000000..9570d89bc --- /dev/null +++ b/test/fixtures/core.scale/title/default.js @@ -0,0 +1,73 @@ +module.exports = { + config: { + type: 'line', + options: { + events: [], + scales: { + top: { + type: 'linear', + position: 'top', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + text: 'top' + } + }, + left: { + type: 'linear', + position: 'left', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + text: 'left' + } + }, + bottom: { + type: 'linear', + position: 'bottom', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + text: 'bottom' + } + }, + right: { + type: 'linear', + position: 'right', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + text: 'right' + } + }, + } + } + }, + options: { + spriteText: true, + canvas: { + height: 256, + width: 256 + }, + } +}; diff --git a/test/fixtures/core.scale/title/default.png b/test/fixtures/core.scale/title/default.png new file mode 100644 index 000000000..3dc2270ec Binary files /dev/null and b/test/fixtures/core.scale/title/default.png differ diff --git a/test/fixtures/core.scale/title/multi-line/align-end.js b/test/fixtures/core.scale/title/multi-line/align-end.js new file mode 100644 index 000000000..b6d980b06 --- /dev/null +++ b/test/fixtures/core.scale/title/multi-line/align-end.js @@ -0,0 +1,77 @@ +module.exports = { + config: { + type: 'line', + options: { + events: [], + scales: { + top: { + type: 'linear', + position: 'top', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'end', + text: ['top', 'line2', 'line3'] + } + }, + left: { + type: 'linear', + position: 'left', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'end', + text: ['left', 'line2', 'line3'] + } + }, + bottom: { + type: 'linear', + position: 'bottom', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'end', + text: ['bottom', 'line2', 'line3'] + } + }, + right: { + type: 'linear', + position: 'right', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'end', + text: ['right', 'line2', 'line3'] + } + }, + } + } + }, + options: { + spriteText: true, + canvas: { + height: 256, + width: 256 + }, + } +}; diff --git a/test/fixtures/core.scale/title/multi-line/align-end.png b/test/fixtures/core.scale/title/multi-line/align-end.png new file mode 100644 index 000000000..155da25ec Binary files /dev/null and b/test/fixtures/core.scale/title/multi-line/align-end.png differ diff --git a/test/fixtures/core.scale/title/multi-line/align-start.js b/test/fixtures/core.scale/title/multi-line/align-start.js new file mode 100644 index 000000000..c0e97cb07 --- /dev/null +++ b/test/fixtures/core.scale/title/multi-line/align-start.js @@ -0,0 +1,77 @@ +module.exports = { + config: { + type: 'line', + options: { + events: [], + scales: { + top: { + type: 'linear', + position: 'top', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'start', + text: ['top', 'line2', 'line3'] + } + }, + left: { + type: 'linear', + position: 'left', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'start', + text: ['left', 'line2', 'line3'] + } + }, + bottom: { + type: 'linear', + position: 'bottom', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'start', + text: ['bottom', 'line2', 'line3'] + } + }, + right: { + type: 'linear', + position: 'right', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + align: 'start', + text: ['right', 'line2', 'line3'] + } + }, + } + } + }, + options: { + spriteText: true, + canvas: { + height: 256, + width: 256 + }, + } +}; diff --git a/test/fixtures/core.scale/title/multi-line/align-start.png b/test/fixtures/core.scale/title/multi-line/align-start.png new file mode 100644 index 000000000..dcba4607a Binary files /dev/null and b/test/fixtures/core.scale/title/multi-line/align-start.png differ diff --git a/test/fixtures/core.scale/title/multi-line/default.js b/test/fixtures/core.scale/title/multi-line/default.js new file mode 100644 index 000000000..c320d0f69 --- /dev/null +++ b/test/fixtures/core.scale/title/multi-line/default.js @@ -0,0 +1,73 @@ +module.exports = { + config: { + type: 'line', + options: { + events: [], + scales: { + top: { + type: 'linear', + position: 'top', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + text: ['top', 'line2', 'line3'] + } + }, + left: { + type: 'linear', + position: 'left', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + text: ['left', 'line2', 'line3'] + } + }, + bottom: { + type: 'linear', + position: 'bottom', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + text: ['bottom', 'line2', 'line3'] + } + }, + right: { + type: 'linear', + position: 'right', + ticks: { + display: false + }, + gridLines: { + display: false + }, + title: { + display: true, + text: ['right', 'line2', 'line3'] + } + }, + } + } + }, + options: { + spriteText: true, + canvas: { + height: 256, + width: 256 + }, + } +}; diff --git a/test/fixtures/core.scale/title/multi-line/default.png b/test/fixtures/core.scale/title/multi-line/default.png new file mode 100644 index 000000000..f53f33e0e Binary files /dev/null and b/test/fixtures/core.scale/title/multi-line/default.png differ