mirror of
https://github.com/chartjs/Chart.js.git
synced 2024-10-06 12:19:08 +02:00
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:
parent
913a01a3a6
commit
5faffae81b
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
},
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user