Built-in and extensible plugin system for additional functionality. Plugins provide lifecycle hooks and configurable features that extend chart behavior.
Displays chart titles and subtitles.
const Title: Plugin = {
id: 'title',
defaults: object,
// Plugin implementation
};
interface TitleOptions {
display?: boolean;
position?: 'top' | 'left' | 'bottom' | 'right';
align?: 'start' | 'center' | 'end';
color?: Color;
font?: FontSpec;
fullSize?: boolean;
padding?: number | Padding;
text?: string | string[];
}Usage Example:
const config = {
type: 'bar',
data: { /* data */ },
options: {
plugins: {
title: {
display: true,
text: 'Chart Title',
position: 'top',
align: 'center',
color: '#333',
font: {
size: 18,
weight: 'bold'
},
padding: {
top: 10,
bottom: 30
}
}
}
}
};Displays chart legend for datasets.
const Legend: Plugin = {
id: 'legend',
defaults: object,
// Plugin implementation
};
interface LegendOptions {
display?: boolean;
position?: 'top' | 'left' | 'bottom' | 'right' | 'chartArea';
align?: 'start' | 'center' | 'end';
maxHeight?: number;
maxWidth?: number;
fullSize?: boolean;
onClick?: (event: ChartEvent, legendItem: LegendItem, legend: LegendElement) => void;
onHover?: (event: ChartEvent, legendItem: LegendItem, legend: LegendElement) => void;
onLeave?: (event: ChartEvent, legendItem: LegendItem, legend: LegendElement) => void;
reverse?: boolean;
labels?: LegendLabelOptions;
rtl?: boolean;
textDirection?: string;
title?: LegendTitleOptions;
}
interface LegendLabelOptions {
boxWidth?: number;
boxHeight?: number;
color?: Color;
font?: FontSpec;
padding?: number;
generateLabels?: (chart: Chart) => LegendItem[];
filter?: (item: LegendItem, data: ChartData) => boolean;
sort?: (a: LegendItem, b: LegendItem, data: ChartData) => number;
pointStyle?: PointStyle | HTMLImageElement | HTMLCanvasElement;
textAlign?: 'left' | 'right' | 'center';
usePointStyle?: boolean;
useBorderRadius?: boolean;
borderRadius?: number;
}
interface LegendItem {
text: string;
lineCap?: CanvasLineCap;
lineDash?: number[];
lineDashOffset?: number;
lineJoin?: CanvasLineJoin;
lineWidth?: number;
strokeStyle?: Color;
pointStyle?: PointStyle | HTMLImageElement | HTMLCanvasElement;
rotation?: number;
boxWidth?: number;
boxHeight?: number;
color?: Color;
fillStyle?: Color;
fontColor?: Color;
hidden?: boolean;
index?: number;
datasetIndex?: number;
}Usage Example:
const config = {
type: 'line',
data: { /* data */ },
options: {
plugins: {
legend: {
display: true,
position: 'bottom',
align: 'center',
labels: {
usePointStyle: true,
padding: 20,
font: {
size: 14
},
generateLabels: (chart) => {
// Custom label generation
return chart.data.datasets.map((dataset, i) => ({
text: dataset.label,
fillStyle: dataset.backgroundColor,
strokeStyle: dataset.borderColor,
hidden: !chart.isDatasetVisible(i),
index: i
}));
}
}
}
}
}
};Interactive tooltips on hover.
const Tooltip: Plugin = {
id: 'tooltip',
defaults: object,
// Plugin implementation
};
interface TooltipOptions {
enabled?: boolean;
external?: (context: TooltipContext) => void;
mode?: InteractionMode;
intersect?: boolean;
position?: 'average' | 'nearest' | TooltipPositioner;
callbacks?: TooltipCallbacks;
itemSort?: (a: TooltipItem, b: TooltipItem, data: ChartData) => number;
filter?: (tooltipItem: TooltipItem, index: number, tooltipItems: TooltipItem[], data: ChartData) => boolean;
backgroundColor?: Color;
titleColor?: Color;
titleFont?: FontSpec;
titleAlign?: 'left' | 'center' | 'right';
titleSpacing?: number;
titleMarginBottom?: number;
bodyColor?: Color;
bodyFont?: FontSpec;
bodyAlign?: 'left' | 'center' | 'right';
bodySpacing?: number;
footerColor?: Color;
footerFont?: FontSpec;
footerAlign?: 'left' | 'center' | 'right';
footerSpacing?: number;
footerMarginTop?: number;
padding?: number | Padding;
caretPadding?: number;
caretSize?: number;
cornerRadius?: number;
multiKeyBackground?: Color;
displayColors?: boolean;
boxWidth?: number;
boxHeight?: number;
boxPadding?: number;
usePointStyle?: boolean;
borderColor?: Color;
borderWidth?: number;
rtl?: boolean;
textDirection?: string;
xAlign?: 'left' | 'center' | 'right';
yAlign?: 'top' | 'center' | 'bottom';
}
interface TooltipCallbacks {
beforeTitle?: (tooltipItems: TooltipItem[]) => string | string[];
title?: (tooltipItems: TooltipItem[]) => string | string[];
afterTitle?: (tooltipItems: TooltipItem[]) => string | string[];
beforeBody?: (tooltipItems: TooltipItem[]) => string | string[];
beforeLabel?: (tooltipItem: TooltipItem) => string | string[];
label?: (tooltipItem: TooltipItem) => string | string[];
labelColor?: (tooltipItem: TooltipItem) => TooltipLabelStyle;
labelTextColor?: (tooltipItem: TooltipItem) => Color;
labelPointStyle?: (tooltipItem: TooltipItem) => PointStyle | { pointStyle: PointStyle; rotation: number };
afterLabel?: (tooltipItem: TooltipItem) => string | string[];
afterBody?: (tooltipItems: TooltipItem[]) => string | string[];
beforeFooter?: (tooltipItems: TooltipItem[]) => string | string[];
footer?: (tooltipItems: TooltipItem[]) => string | string[];
afterFooter?: (tooltipItems: TooltipItem[]) => string | string[];
}
interface TooltipItem {
chart: Chart;
label: string;
parsed: ParsedDataType;
raw: unknown;
formattedValue: string;
dataset: ChartDataset;
datasetIndex: number;
dataIndex: number;
element: Element;
}Displays chart subtitles.
const SubTitle: Plugin = {
id: 'subtitle',
defaults: object,
// Plugin implementation
};
// SubTitleOptions extends TitleOptions
interface SubTitleOptions extends TitleOptions {
// Inherits all title options
}Fills areas between datasets or to axes.
const Filler: Plugin = {
id: 'filler',
defaults: object,
// Plugin implementation
};
interface FillerOptions {
propagate?: boolean;
drawTime?: 'beforeDatasetDraw' | 'beforeDatasetsDraw';
}
// Fill configurations (used in dataset options)
type FillTarget = boolean | number | string | 'start' | 'end' | 'origin' | 'stack' | 'shape' | { target: FillTarget; above?: Color; below?: Color };Usage Example:
const config = {
type: 'line',
data: {
datasets: [{
label: 'Dataset 1',
data: [10, 20, 30, 40],
fill: 'start', // Fill to start of chart
backgroundColor: 'rgba(75, 192, 192, 0.2)'
}, {
label: 'Dataset 2',
data: [15, 25, 35, 45],
fill: '-1', // Fill to previous dataset
backgroundColor: 'rgba(255, 99, 132, 0.2)'
}]
},
options: {
plugins: {
filler: {
propagate: true
}
}
}
};Reduces data points for performance with large datasets.
const Decimation: Plugin = {
id: 'decimation',
defaults: object,
// Plugin implementation
};
interface DecimationOptions {
enabled?: boolean;
algorithm?: 'lttb' | 'min-max';
samples?: number;
threshold?: number;
}Automatic color assignment for datasets.
const Colors: Plugin = {
id: 'colors',
defaults: object,
// Plugin implementation
};
interface ColorsOptions {
enabled?: boolean;
forceOverride?: boolean;
}Base interface for creating custom plugins.
interface Plugin<TType extends ChartType = ChartType, O = object> {
id: string;
// Lifecycle hooks
beforeInit?(chart: Chart<TType>, args: EmptyObject, options: O): void;
afterInit?(chart: Chart<TType>, args: EmptyObject, options: O): void;
beforeUpdate?(chart: Chart<TType>, args: UpdateArgs, options: O): boolean | void;
afterUpdate?(chart: Chart<TType>, args: UpdateArgs, options: O): void;
beforeElementsUpdate?(chart: Chart<TType>, args: EmptyObject, options: O): void;
beforeLayout?(chart: Chart<TType>, args: EmptyObject, options: O): boolean | void;
afterLayout?(chart: Chart<TType>, args: EmptyObject, options: O): void;
beforeDatasetsUpdate?(chart: Chart<TType>, args: UpdateArgs, options: O): boolean | void;
afterDatasetsUpdate?(chart: Chart<TType>, args: UpdateArgs, options: O): void;
beforeDatasetUpdate?(chart: Chart<TType>, args: DatasetUpdateArgs, options: O): boolean | void;
afterDatasetUpdate?(chart: Chart<TType>, args: DatasetUpdateArgs, options: O): void;
beforeRender?(chart: Chart<TType>, args: EmptyObject, options: O): boolean | void;
afterRender?(chart: Chart<TType>, args: EmptyObject, options: O): void;
beforeDraw?(chart: Chart<TType>, args: EmptyObject, options: O): boolean | void;
afterDraw?(chart: Chart<TType>, args: EmptyObject, options: O): void;
beforeDatasetsDraw?(chart: Chart<TType>, args: EmptyObject, options: O): boolean | void;
afterDatasetsDraw?(chart: Chart<TType>, args: EmptyObject, options: O): void;
beforeDatasetDraw?(chart: Chart<TType>, args: DatasetDrawArgs, options: O): boolean | void;
afterDatasetDraw?(chart: Chart<TType>, args: DatasetDrawArgs, options: O): void;
beforeTooltipDraw?(chart: Chart<TType>, args: TooltipDrawArgs, options: O): boolean | void;
afterTooltipDraw?(chart: Chart<TType>, args: TooltipDrawArgs, options: O): void;
beforeEvent?(chart: Chart<TType>, args: EventArgs, options: O): boolean | void;
afterEvent?(chart: Chart<TType>, args: EventArgs, options: O): void;
resize?(chart: Chart<TType>, args: ResizeArgs, options: O): void;
reset?(chart: Chart<TType>, args: EmptyObject, options: O): void;
stop?(chart: Chart<TType>, args: EmptyObject, options: O): void;
destroy?(chart: Chart<TType>, args: EmptyObject, options: O): void;
// Optional properties
defaults?: object;
defaultRoutes?: { [property: string]: string };
descriptors?: { [property: string]: boolean };
}Usage Example (Custom Plugin):
const customPlugin = {
id: 'customPlugin',
beforeDraw: (chart, args, options) => {
const { ctx, chartArea } = chart;
// Custom drawing logic
ctx.fillStyle = options.backgroundColor || 'lightgray';
ctx.fillRect(chartArea.left, chartArea.top, chartArea.width, chartArea.height);
}
};
// Register and use
Chart.register(customPlugin);
const config = {
type: 'bar',
data: { /* data */ },
plugins: [customPlugin],
options: {
plugins: {
customPlugin: {
backgroundColor: 'lightblue'
}
}
}
};Plugins must be registered before use.
import {
Chart,
Title,
Tooltip,
Legend,
SubTitle,
Filler,
Decimation,
Colors
} from 'chart.js';
// Register built-in plugins
Chart.register(
Title,
Tooltip,
Legend,
SubTitle,
Filler,
Decimation,
Colors
);type InteractionMode = 'point' | 'nearest' | 'index' | 'dataset' | 'x' | 'y';
type PointStyle = 'circle' | 'cross' | 'crossRot' | 'dash' | 'line' | 'rect' | 'rectRounded' | 'rectRot' | 'star' | 'triangle';
interface FontSpec {
family?: string;
size?: number;
style?: 'normal' | 'italic' | 'oblique';
weight?: string | number;
lineHeight?: number | string;
}
interface Padding {
top?: number;
right?: number;
bottom?: number;
left?: number;
}
interface EmptyObject {}
interface UpdateArgs {
mode: UpdateMode;
}
interface DatasetUpdateArgs {
index: number;
mode: UpdateMode;
}
interface EventArgs {
event: ChartEvent;
replay: boolean;
changed?: boolean;
cancelable: boolean;
inChartArea: boolean;
}
type Color = string | CanvasGradient | CanvasPattern;
interface ChartEvent {
type: string;
x?: number;
y?: number;
native?: Event;
}
interface TooltipContext<TType extends ChartType = ChartType> {
chart: Chart<TType>;
tooltip: TooltipModel<TType>;
tooltipItems: TooltipItem<TType>[];
}
interface TooltipModel<TType extends ChartType = ChartType> {
opacity: number;
title: string[];
body: TooltipBodyItem[];
footer: string[];
x: number;
y: number;
width: number;
height: number;
caretX: number;
caretY: number;
}
interface TooltipBodyItem {
before: string[];
lines: string[];
after: string[];
}
type TooltipPositioner = (elements: Element[], eventPosition: Point) => Point;
type ParsedDataType = { [key: string]: unknown };
interface LegendElement {
chart: Chart;
options: LegendOptions;
legendItems?: LegendItem[];
}