Title plugin cleanup (#8104)

* Title plugin cleanup

* more cleanup

* cc

* center formula

* Fix / update sample

* Restore functionality on RTL page
This commit is contained in:
Jukka Kurkela 2020-11-26 15:07:01 +02:00 committed by GitHub
parent 913a01a3a6
commit 5faffae81b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 116 additions and 124 deletions

View File

@ -15,6 +15,10 @@
width: 500px; width: 500px;
margin-left: 40px; margin-left: 40px;
margin-right: 40px; margin-right: 40px;
box-sizing: content-box;
border: 1px solid rgb(240, 240, 240);
border-radius: 4px;
margin: 4px;
} }
.container { .container {
display: flex; display: flex;
@ -45,6 +49,24 @@
<div class="chart-container"> <div class="chart-container">
<canvas id="chart-title-left-end"></canvas> <canvas id="chart-title-left-end"></canvas>
</div> </div>
<div class="chart-container">
<canvas id="chart-title-bottom-start"></canvas>
</div>
<div class="chart-container">
<canvas id="chart-title-bottom-center"></canvas>
</div>
<div class="chart-container">
<canvas id="chart-title-bottom-end"></canvas>
</div>
<div class="chart-container">
<canvas id="chart-title-right-start"></canvas>
</div>
<div class="chart-container">
<canvas id="chart-title-right-center"></canvas>
</div>
<div class="chart-container">
<canvas id="chart-title-right-end"></canvas>
</div>
</div> </div>
<script> <script>
var color = Chart.helpers.color; var color = Chart.helpers.color;
@ -75,6 +97,12 @@
legend: { legend: {
display: false display: false
}, },
title: {
align: titleAlignment,
display: true,
position: titlePosition,
text: 'Title Position: ' + titlePosition + ', Align: ' + titleAlignment
}
}, },
scales: { scales: {
x: { x: {
@ -91,12 +119,6 @@
labelString: 'Value' labelString: 'Value'
} }
} }
},
title: {
align: titleAlignment,
display: true,
position: titlePosition,
text: 'Title Position: ' + titlePosition + ', Align: ' + titleAlignment
} }
} }
}; };
@ -133,6 +155,36 @@
titleAlignment: 'end', titleAlignment: 'end',
titlePosition: 'left', titlePosition: 'left',
color: 'purple' color: 'purple'
}, {
id: 'chart-title-bottom-start',
titleAlignment: 'start',
titlePosition: 'bottom',
color: 'red'
}, {
id: 'chart-title-bottom-center',
titleAlignment: 'center',
titlePosition: 'bottom',
color: 'orange'
}, {
id: 'chart-title-bottom-end',
titleAlignment: 'end',
titlePosition: 'bottom',
color: 'yellow'
}, {
id: 'chart-title-right-start',
titleAlignment: 'start',
titlePosition: 'right',
color: 'green'
}, {
id: 'chart-title-right-center',
titleAlignment: 'center',
titlePosition: 'right',
color: 'blue'
}, {
id: 'chart-title-right-end',
titleAlignment: 'end',
titlePosition: 'right',
color: 'purple'
}].forEach(function(details) { }].forEach(function(details) {
var ctx = document.getElementById(details.id).getContext('2d'); var ctx = document.getElementById(details.id).getContext('2d');
var config = createConfig(details.titlePosition, details.titleAlignment, details.color); var config = createConfig(details.titlePosition, details.titleAlignment, details.color);

View File

@ -1,7 +1,9 @@
import defaults from '../core/core.defaults';
import Element from '../core/core.element'; import Element from '../core/core.element';
import layouts from '../core/core.layouts'; import layouts from '../core/core.layouts';
import {PI, isArray, mergeIf, toPadding, toFont} from '../helpers'; import {PI, isArray, toPadding, toFont} from '../helpers';
const toLeftRightCenter = (align) => align === 'start' ? 'left' : align === 'end' ? 'right' : 'center';
const alignStartEnd = (align, start, end) => align === 'start' ? start : align === 'end' ? end : (start + end) / 2;
export class Title extends Element { export class Title extends Element {
constructor(config) { constructor(config) {
@ -27,45 +29,18 @@ export class Title extends Element {
this.fullWidth = undefined; this.fullWidth = undefined;
} }
// These methods are ordered by lifecycle. Utilities then follow.
beforeUpdate() {}
update(maxWidth, maxHeight, margins) { update(maxWidth, maxHeight, margins) {
const me = this; const me = this;
// Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
me.beforeUpdate();
// Absorb the master measurements
me.maxWidth = maxWidth; me.maxWidth = maxWidth;
me.maxHeight = maxHeight; me.maxHeight = maxHeight;
me._margins = margins; me._margins = margins;
// Dimensions
me.beforeSetDimensions();
me.setDimensions(); me.setDimensions();
me.afterSetDimensions();
// Labels
me.beforeBuildLabels();
me.buildLabels();
me.afterBuildLabels();
// Fit
me.beforeFit();
me.fit(); me.fit();
me.afterFit();
//
me.afterUpdate();
} }
afterUpdate() {}
beforeSetDimensions() {}
setDimensions() { setDimensions() {
const me = this; const me = this;
// Set the unconstrained dimension before label rotation // Set the unconstrained dimension before label rotation
@ -83,16 +58,6 @@ export class Title extends Element {
} }
} }
afterSetDimensions() {}
beforeBuildLabels() {}
buildLabels() {}
afterBuildLabels() {}
beforeFit() {}
fit() { fit() {
const me = this; const me = this;
const opts = me.options; const opts = me.options;
@ -111,15 +76,36 @@ export class Title extends Element {
me.height = minSize.height = isHorizontal ? textSize : me.maxHeight; me.height = minSize.height = isHorizontal ? textSize : me.maxHeight;
} }
afterFit() {}
// Shared Methods
isHorizontal() { isHorizontal() {
const pos = this.options.position; const pos = this.options.position;
return pos === 'top' || pos === 'bottom'; return pos === 'top' || pos === 'bottom';
} }
// Actually draw the title block on the canvas _drawArgs(offset) {
const {top, left, bottom, right, options} = this;
const align = options.align;
let rotation = 0;
let maxWidth, titleX, titleY;
if (this.isHorizontal()) {
titleX = alignStartEnd(align, left, right);
titleY = top + offset;
maxWidth = right - left;
} else {
if (options.position === 'left') {
titleX = left + offset;
titleY = alignStartEnd(align, bottom, top);
rotation = PI * -0.5;
} else {
titleX = right - offset;
titleY = alignStartEnd(align, top, bottom);
rotation = PI * 0.5;
}
maxWidth = bottom - top;
}
return {titleX, titleY, maxWidth, rotation};
}
draw() { draw() {
const me = this; const me = this;
const ctx = me.ctx; const ctx = me.ctx;
@ -132,53 +118,7 @@ export class Title extends Element {
const fontOpts = toFont(opts.font, me.chart.options.font); const fontOpts = toFont(opts.font, me.chart.options.font);
const lineHeight = fontOpts.lineHeight; const lineHeight = fontOpts.lineHeight;
const offset = lineHeight / 2 + me._padding.top; const offset = lineHeight / 2 + me._padding.top;
let rotation = 0; const {titleX, titleY, maxWidth, rotation} = me._drawArgs(offset);
const top = me.top;
const left = me.left;
const bottom = me.bottom;
const right = me.right;
let maxWidth, titleX, titleY;
let align;
// Horizontal
if (me.isHorizontal()) {
switch (opts.align) {
case 'start':
titleX = left;
align = 'left';
break;
case 'end':
titleX = right;
align = 'right';
break;
default:
titleX = left + ((right - left) / 2);
align = 'center';
break;
}
titleY = top + offset;
maxWidth = right - left;
} else {
titleX = opts.position === 'left' ? left + offset : right - offset;
switch (opts.align) {
case 'start':
titleY = opts.position === 'left' ? bottom : top;
align = 'left';
break;
case 'end':
titleY = opts.position === 'left' ? top : bottom;
align = 'right';
break;
default:
titleY = top + ((bottom - top) / 2);
align = 'center';
break;
}
maxWidth = bottom - top;
rotation = PI * (opts.position === 'left' ? -0.5 : 0.5);
}
ctx.save(); ctx.save();
@ -187,7 +127,7 @@ export class Title extends Element {
ctx.translate(titleX, titleY); ctx.translate(titleX, titleY);
ctx.rotate(rotation); ctx.rotate(rotation);
ctx.textAlign = align; ctx.textAlign = toLeftRightCenter(opts.align);
ctx.textBaseline = 'middle'; ctx.textBaseline = 'middle';
const text = opts.text; const text = opts.text;
@ -205,7 +145,7 @@ export class Title extends Element {
} }
} }
function createNewTitleBlockAndAttach(chart, titleOpts) { function createTitle(chart, titleOpts) {
const title = new Title({ const title = new Title({
ctx: chart.ctx, ctx: chart.ctx,
options: titleOpts, options: titleOpts,
@ -217,42 +157,42 @@ function createNewTitleBlockAndAttach(chart, titleOpts) {
chart.titleBlock = title; chart.titleBlock = title;
} }
function removeTitle(chart) {
const title = chart.titleBlock;
if (title) {
layouts.removeBox(chart, title);
delete chart.titleBlock;
}
}
function createOrUpdateTitle(chart, options) {
const title = chart.titleBlock;
if (title) {
layouts.configure(chart, title, options);
title.options = options;
} else {
createTitle(chart, options);
}
}
export default { export default {
id: 'title', id: 'title',
/** /**
* Backward compatibility: since 2.1.5, the title is registered as a plugin, making * For tests
* Chart.Title obsolete. To avoid a breaking change, we export the Title as part of
* the plugin, which one will be re-exposed in the chart.js file.
* https://github.com/chartjs/Chart.js/pull/2640
* @private * @private
*/ */
_element: Title, _element: Title,
beforeInit(chart) { beforeInit(chart, options) {
const titleOpts = chart.options.plugins.title; createTitle(chart, options);
if (titleOpts) {
createNewTitleBlockAndAttach(chart, titleOpts);
}
}, },
beforeUpdate(chart) { beforeUpdate(chart, args, options) {
const titleOpts = chart.options.plugins.title; if (options === false) {
const titleBlock = chart.titleBlock; removeTitle(chart);
} else {
if (titleOpts) { createOrUpdateTitle(chart, options);
mergeIf(titleOpts, defaults.plugins.title);
if (titleBlock) {
layouts.configure(chart, titleBlock, titleOpts);
titleBlock.options = titleOpts;
} else {
createNewTitleBlockAndAttach(chart, titleOpts);
}
} else if (titleBlock) {
layouts.removeBox(chart, titleBlock);
delete chart.titleBlock;
} }
}, },