Chart.js 3.x:如何在tooltip内设置不同字号(非外部HTML tooltip)
Chart.js 3.x 实现Tooltip内部分文本字号差异化(无需外部HTML Tooltip)
问题背景
当前使用Chart.js 3.x,已通过plugins.tooltip及回调函数自定义Tooltip样式,配置示例如下:
tooltip: { callbacks: { footer: function (context) { return "69%"; }, label: function (context) { return "TEST"; } }, backgroundColor: "#FFF", borderWidth: 1, borderColor: "black", titleFont: { size: 14, weight: "light", }, footerFont: { size: 20, weight: "bold", }, titleColor: "rgba(51, 51, 51, 1)", bodyColor: "rgba(51, 51, 51, 1)", footerColor: "black", displayColors: false, titleAlign: "center", bodyAlign: "center", footerAlign: "center", padding: 8, },
需求:让Tooltip中类似69%里的%符号使用更小字号,且不想使用外部HTML Tooltip方案。
解决方案:利用tooltip.custom自定义Canvas绘制
Chart.js默认Tooltip的回调仅能返回纯文本,无法单独设置局部样式,但可以通过tooltip.custom函数完全接管Tooltip的渲染逻辑,直接使用Canvas API实现差异化文本样式。
修改后的配置示例
tooltip: { // 关闭默认Tooltip渲染,启用自定义逻辑 enabled: false, custom: function(context) { const tooltip = context.tooltip; // 无内容时不渲染 if (tooltip.opacity === 0) return; const ctx = context.chart.ctx; const chart = context.chart; // 绘制Tooltip容器(背景+边框) ctx.save(); ctx.fillStyle = '#FFF'; ctx.strokeStyle = 'black'; ctx.lineWidth = 1; ctx.fillRect(tooltip.x, tooltip.y, tooltip.width, tooltip.height); ctx.strokeRect(tooltip.x, tooltip.y, tooltip.width, tooltip.height); // 处理Footer文本(拆分数字与%符号) if (tooltip.footer && tooltip.footer.length > 0) { const footerText = tooltip.footer[0]; const numPart = footerText.slice(0, -1); const symbolPart = footerText.slice(-1); // 绘制数字(大字号) ctx.font = 'bold 20px sans-serif'; ctx.fillStyle = 'black'; const numWidth = ctx.measureText(numPart).width; // 计算居中位置 const symbolWidth = ctx.measureText(symbolPart).width; const totalTextWidth = numWidth + symbolWidth; const startX = tooltip.x + (tooltip.width - totalTextWidth) / 2; const centerY = tooltip.y + tooltip.height / 2 + 8; // 垂直居中偏移量 ctx.fillText(numPart, startX, centerY); // 绘制%符号(小字号) ctx.font = 'bold 14px sans-serif'; ctx.fillText(symbolPart, startX + numWidth, centerY - 3); // 垂直对齐调整 } // 如需处理Label文本,可参照上述逻辑添加 if (tooltip.body && tooltip.body.length > 0) { const labelText = tooltip.body[0].lines[0]; // 此处可按需拆分Label文本并设置不同样式绘制 ctx.font = '14px light sans-serif'; ctx.fillStyle = 'rgba(51, 51, 51, 1)'; ctx.textAlign = 'center'; ctx.fillText(labelText, tooltip.x + tooltip.width / 2, tooltip.y + 20); } ctx.restore(); }, // 保留原有尺寸相关配置,用于Tooltip容器的自动计算 padding: 8, }
关键逻辑说明
- 关闭默认渲染:设置
enabled: false,让自定义逻辑接管Tooltip绘制 - 容器绘制:用Canvas API手动绘制Tooltip的背景和边框,还原原有样式
- 文本拆分与绘制:将目标文本拆分为需要大字号的数字部分和小字号的符号部分,分别设置
font属性后绘制 - 对齐处理:通过
measureText计算文本宽度,实现水平居中;调整垂直坐标让不同字号的文本对齐更自然
内容的提问来源于stack exchange,提问作者amu03
相关产品推荐
相关产品推荐

