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;
margin-left: 40px;
margin-right: 40px;
box-sizing: content-box;
border: 1px solid rgb(240, 240, 240);
border-radius: 4px;
margin: 4px;
}
.container {
display: flex;
@ -45,6 +49,24 @@
<div class="chart-container">
<canvas id="chart-title-left-end"></canvas>
</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>
<script>
var color = Chart.helpers.color;
@ -75,6 +97,12 @@
legend: {
display: false
},
title: {
align: titleAlignment,
display: true,
position: titlePosition,
text: 'Title Position: ' + titlePosition + ', Align: ' + titleAlignment
}
},
scales: {
x: {
@ -91,12 +119,6 @@
labelString: 'Value'
}
}
},
title: {
align: titleAlignment,
display: true,
position: titlePosition,
text: 'Title Position: ' + titlePosition + ', Align: ' + titleAlignment
}
}
};
@ -133,6 +155,36 @@
titleAlignment: 'end',
titlePosition: 'left',
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) {
var ctx = document.getElementById(details.id).getContext('2d');
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 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 {
constructor(config) {
@ -27,45 +29,18 @@ export class Title extends Element {
this.fullWidth = undefined;
}
// These methods are ordered by lifecycle. Utilities then follow.
beforeUpdate() {}
update(maxWidth, maxHeight, margins) {
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.maxHeight = maxHeight;
me._margins = margins;
// Dimensions
me.beforeSetDimensions();
me.setDimensions();
me.afterSetDimensions();
// Labels
me.beforeBuildLabels();
me.buildLabels();
me.afterBuildLabels();
// Fit
me.beforeFit();
me.fit();
me.afterFit();
//
me.afterUpdate();
}
afterUpdate() {}
beforeSetDimensions() {}
setDimensions() {
const me = this;
// Set the unconstrained dimension before label rotation
@ -83,16 +58,6 @@ export class Title extends Element {
}
}
afterSetDimensions() {}
beforeBuildLabels() {}
buildLabels() {}
afterBuildLabels() {}
beforeFit() {}
fit() {
const me = this;
const opts = me.options;
@ -111,15 +76,36 @@ export class Title extends Element {
me.height = minSize.height = isHorizontal ? textSize : me.maxHeight;
}
afterFit() {}
// Shared Methods
isHorizontal() {
const pos = this.options.position;
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() {
const me = this;
const ctx = me.ctx;
@ -132,53 +118,7 @@ export class Title extends Element {
const fontOpts = toFont(opts.font, me.chart.options.font);
const lineHeight = fontOpts.lineHeight;
const offset = lineHeight / 2 + me._padding.top;
let rotation = 0;
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);
}
const {titleX, titleY, maxWidth, rotation} = me._drawArgs(offset);
ctx.save();
@ -187,7 +127,7 @@ export class Title extends Element {
ctx.translate(titleX, titleY);
ctx.rotate(rotation);
ctx.textAlign = align;
ctx.textAlign = toLeftRightCenter(opts.align);
ctx.textBaseline = 'middle';
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({
ctx: chart.ctx,
options: titleOpts,
@ -217,42 +157,42 @@ function createNewTitleBlockAndAttach(chart, titleOpts) {
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 {
id: 'title',
/**
* Backward compatibility: since 2.1.5, the title is registered as a plugin, making
* 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
* For tests
* @private
*/
_element: Title,
beforeInit(chart) {
const titleOpts = chart.options.plugins.title;
if (titleOpts) {
createNewTitleBlockAndAttach(chart, titleOpts);
}
beforeInit(chart, options) {
createTitle(chart, options);
},
beforeUpdate(chart) {
const titleOpts = chart.options.plugins.title;
const titleBlock = chart.titleBlock;
if (titleOpts) {
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;
beforeUpdate(chart, args, options) {
if (options === false) {
removeTitle(chart);
} else {
createOrUpdateTitle(chart, options);
}
},