You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ChartJs 3.5.1多行轴标签如何逐行控制字体配置选项?

Chart.js多行轴标签独立字体样式实现

我希望通过现有配置或开发插件的方式,接入轴标签的渲染流程,实现对多行标签每一行的字体属性独立控制,比如最终渲染效果类似主标签加下方子标签的结构,主标签加粗且字号更大,子标签字重正常且字号更小。

我当前使用ChartJs 3.5.1版本渲染水平条形图,左侧的数据集标签对应y轴配置,目前已经尝试了以下几种方案均未成功:

  • 接入tick回调:但该函数传入的参数不是标签文本,而是数据行的序号/序数,即便能按照示例正常运行,该能力也仅能修改标签内容,无法调整字体相关配置。
  • 将ticks的font配置设置为数组:但该配置仅能实现不同数据行的标签字体差异化,无法对同一个标签的不同行设置不同的字体属性。
  • 使用afterDraw这类插件钩子调整样式:但此时的配置仍将多行标签视为一个整体,无法拆分配置不同行的样式。
  • 查阅项目的历史PR(多为新增多行标签支持、该领域相关bug修复的PR)也未获得可行的实现思路。

如果目前没有现成的通过插件或现有配置实现的方案,请问如果要提交PR实现该功能应该从哪里入手?

更新:根据我提交的对应ChartJs feature request的回复,以及下方的采纳答案,目前实现该需求的唯一方式是自定义插件。

以下是我使用的核心配置(因为我的使用场景较窄,我将部分配置硬编码到了插件中,通用性比采纳答案更低):

// 该配置会传入图表构造函数
const options = {
  //...
  scales: {
    //...
    // 此处针对水平条形图的左侧y轴配置
    y: {
      ticks: {
        // 将原始标签设为白色,后续用自定义子标签覆盖渲染
        color: "white",
        // 保留字体配置占住对应空间,和后续自定义渲染的标签尺寸对齐
        font: {
          size: 22,
          weight: "bold"
        }
      }
    },
    //...
  }
};

// 自定义插件,同样需要传入图表构造函数
const customSubLabelsPlugin = {
  id: "customSubLabels",
  afterDraw: (chart, args, opts) => {
    // 初始化需要的变量
    const {
      ctx,
      // 仅修改目标y轴的标签,其他轴不受影响
      scales: { y }
    } = chart;
    const labelItems = y._labelItems;
    const fontStringSubTitle = "16px Helvetica,Arial,sans-serif";
    const fontStringMain = "bold 22px Helvetica,Arial,sans-serif";

    // 遍历每个数据集标签
    for (let i = 0; i < labelItems.length; i++) {
      let labelItem = labelItems[i];

      // 默认标签为数组格式,非数组自动包裹为数组适配后续逻辑
      const label = Array.isArray(labelItem.label)
        ? labelItem.label
        : [labelItem.label];

      // 在画布上绘制新的文本标签
      let offset = 0;
      label.forEach((el) => {
        let elTextMetrics = ctx.measureText(el);

        // 第一行用主标题样式,其余行用子标题样式
        if (labelItem.label.indexOf(el) === 0) {
          ctx.font = fontStringMain;
        } else {
          ctx.font = fontStringSubTitle;
        }

        ctx.save();
        ctx.fillStyle = "#546a6f";
        ctx.fillText(
          el,
          labelItem.translation[0],
          labelItem.translation[1] + labelItem.textOffset + offset
        );
        ctx.restore();
        // 累加行高偏移,避免多行文本重叠
        offset +=
          elTextMetrics.fontBoundingBoxAscent +
          elTextMetrics.fontBoundingBoxDescent;
      });
    }
  }
};

内容的提问来源于stack exchange,提问作者Rich R

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 06:06:03