61 lines
1.8 KiB
TypeScript
61 lines
1.8 KiB
TypeScript
|
|
import { Plugin } from 'chart.js'
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 饼图中心文本插件
|
|||
|
|
* 在 Doughnut/Pie 图表中心显示总金额
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
export interface PieCenterTextOptions {
|
|||
|
|
text?: string
|
|||
|
|
subtext?: string
|
|||
|
|
textColor?: string
|
|||
|
|
subtextColor?: string
|
|||
|
|
fontSize?: number
|
|||
|
|
subFontSize?: number
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export const pieCenterTextPlugin: Plugin = {
|
|||
|
|
id: 'pieCenterText',
|
|||
|
|
afterDraw: (chart: any) => {
|
|||
|
|
const { ctx, chartArea } = chart
|
|||
|
|
|
|||
|
|
if (!chartArea) return
|
|||
|
|
|
|||
|
|
// 计算中心点
|
|||
|
|
const centerX = (chartArea.left + chartArea.right) / 2
|
|||
|
|
const centerY = (chartArea.top + chartArea.bottom) / 2
|
|||
|
|
|
|||
|
|
// 从图表配置中获取插件选项
|
|||
|
|
const pluginOptions = chart.options.plugins?.pieCenterText as PieCenterTextOptions | undefined
|
|||
|
|
|
|||
|
|
if (!pluginOptions) return
|
|||
|
|
|
|||
|
|
const { text, subtext, textColor, subtextColor, fontSize, subFontSize } = pluginOptions
|
|||
|
|
|
|||
|
|
ctx.save()
|
|||
|
|
ctx.textAlign = 'center'
|
|||
|
|
ctx.textBaseline = 'middle'
|
|||
|
|
|
|||
|
|
// 计算字体大小(基于图表高度)
|
|||
|
|
const chartHeight = chartArea.bottom - chartArea.top
|
|||
|
|
const defaultFontSize = Math.max(14, Math.min(32, chartHeight * 0.2))
|
|||
|
|
const defaultSubFontSize = Math.max(10, Math.min(16, chartHeight * 0.12))
|
|||
|
|
|
|||
|
|
// 绘制主文本(金额)
|
|||
|
|
if (text) {
|
|||
|
|
ctx.font = `bold ${fontSize || defaultFontSize}px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif`
|
|||
|
|
ctx.fillStyle = textColor || '#323233'
|
|||
|
|
ctx.fillText(text, centerX, centerY - 5)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 绘制副文本(标签,如"总支出")
|
|||
|
|
if (subtext) {
|
|||
|
|
ctx.font = `${subFontSize || defaultSubFontSize}px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif`
|
|||
|
|
ctx.fillStyle = subtextColor || '#969799'
|
|||
|
|
ctx.fillText(subtext, centerX, centerY + (fontSize || defaultFontSize) * 0.6)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ctx.restore()
|
|||
|
|
}
|
|||
|
|
}
|