HarmonyOS鸿蒙Next中mpchart如何自定义Y轴标签字体?

HarmonyOS鸿蒙Next中mpchart如何自定义Y轴标签字体? 我在使用mpchart绘制图表,现在需要对于Y轴标签使用自定义字体,

我想用setTypeFace()这个接口,但是他只接受FontFamily类型,

我已经全局注册了自定义字体,在Text组件中可以正常使用,但是setTypeFace()不能直接接受注册的自定义字体名字。请问该怎么实现Y轴标签能使用自定义字体?

10 回复

尊敬的开发者,您好,
mpchart的setTypeFace的入参FontFamily限制字体类型为’sans-serif’、‘serif’ 、‘monospace’、’’ 这几种,不支持通过此方式加载自定义字体。mpchart标签底层逻辑是通过Canvas fillText 绘制的,开发者可以通过继承YAxisRenderer类,重写drawYLabels方法的内部逻辑,将自定义字体直接绘制在Canvas上。
若是开发者需要通过setTypeFace设置或者由其他方案实现,还请开发者详细描述下您的场景以及期望实现的方式,感谢:
请问您是在什么样的业务场景中使用该能力,交互流程是怎样的,在哪一个环节遇到了问题?方便说明能力不满足可能带来的影响:什么时间用到?是否高频?有无三方库可以做到?若提供该能力,是否会造成大工作量返工?请您注意提供的内容不要包含您或第三方的非公开信息,如给您带来不便,敬请谅解。

更多关于HarmonyOS鸿蒙Next中mpchart如何自定义Y轴标签字体?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


这个可以用自定义节点+Typeface,在RenderNode绘制,参考代码:

import { RenderNode, DrawContext, NodeController, FrameNode } from '@kit.ArkUI';
import { drawing, text } from '@kit.ArkGraphics2D';

// 自定义文本渲染节点
class MyTextRenderNode extends RenderNode {
  async draw(context: DrawContext) {
    const canvas = context.canvas;
    const myTypeFace = drawing.Typeface.makeFromRawFile($rawfile('font/HarmonyOS_Sans_Black.ttf'));//替换成自己的字体
    let font = new drawing.Font();
    font.setSize(50);
    font.setTypeface(myTypeFace);
    // 创建文本块并绘制
    const textBlob = drawing.TextBlob.makeFromString("Hello World", font, drawing.TextEncoding.TEXT_ENCODING_UTF8);
    canvas.drawTextBlob(textBlob, 60, 100);
  }
}

// 使用 NodeController 管理节点
class MyNodeController extends NodeController {
  private rootNode: FrameNode | null = null;
  private textNode: MyTextRenderNode = new MyTextRenderNode();

  makeNode(uiContext: UIContext): FrameNode {
    this.rootNode = new FrameNode(uiContext);
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      // 设置节点位置和大小
      this.textNode.frame = { x: 0, y: 0, width: 400, height: 600 };
      renderNode.appendChild(this.textNode);
    }
    return this.rootNode;
  }
}

// 在页面中使用 NodeContainer 显示
@Entry
@Component
struct MyPage {
  private controller: MyNodeController = new MyNodeController();
  build() {
    Column() {
      NodeContainer(this.controller)
        .width('100%')
        .height(300)
    }
  }
}

你好,尝试以下方式解决问题:

1、到官方仓库提 issues , 等待官方支持。

2、直接修改源码, FontFamily 类型增加 string,这样就支持传自定义字体。

export type FontFamily = 'sans-serif' | 'serif' | 'monospace' | '';

// 改为
export type FontFamily = 'sans-serif' | 'serif' | 'monospace' | string;

3、如果不想改源码,可以定制渲染类 YAxisRenderer。参考 README

cke_14983.png

上面官方例子是自定义 XAxisRenderer,下面来自定义我们的 YAxisRenderer:

import { YAxisRenderer, YAxis, ViewPortHandler, Transformer, Paint } from
  '@ohos/mpchart';

class CustomYAxisRenderer extends YAxisRenderer {
  private customFont: string;

  constructor(viewPortHandler: ViewPortHandler, yAxis: YAxis, transformer: Transformer,
    customFont: string) {
    super(viewPortHandler, yAxis, transformer);
    this.customFont = customFont;
  }

  // 重写 drawYLabels,在绘制前覆写 font 字符串
  public drawYLabels(c: CanvasRenderingContext2D, fixedPosition: number, positions:
    number[], offset: number, isHorizontalFlip: boolean, isLeftAxis: boolean): void {
    if (this.mAxisLabelPaint) {
      // 参考 this.mAxisLabelPaint.setFontFamily(this.mYAxis.getTypeface()); 拼接得到font
      this.mAxisLabelPaint.font =
        this.mAxisLabelPaint.fontStyle + " " + this.mAxisLabelPaint.fontWeight + " " + this.mAxisLabelPaint.fontSize +
          this.mAxisLabelPaint.fontSizeUnit + " " + this.customFont;
    }
    super.drawYLabels(c, fixedPosition, positions, offset, isHorizontalFlip, isLeftAxis);
  }
}

使用自定义 CustomYAxisRenderer:

// 在 aboutToAppear 中
this.model.setRendererLeftYAxis(
  new CustomYAxisRenderer(
    this.model.getViewPortHandler(),
    this.model.getAxisLeft(),
    this.model.getTransformer(AxisDependency.LEFT),
    '你的字体名'  // font 字符串
  )
);

字体设置参考 CanvasRenderingContext2D font

官方仓库半年回一次issue

HarmonyOS的流畅动画和过渡效果让操作更加顺畅,体验极佳。

尊敬的开发者,您好,

mpchart的setTypeFace的入参FontFamily限制字体类型为’sans-serif’、‘serif’ 、‘monospace’、’’ 这几种,不支持通过此方式加载自定义字体。mpchart标签底层逻辑是通过Canvas fillText 绘制的,开发者可以通过继承YAxisRenderer类,重写drawYLabels方法的内部逻辑,将自定义字体直接绘制在Canvas上。

若是开发者需要通过setTypeFace设置或者由其他方案实现,还请开发者详细描述下您的场景以及期望实现的方式,感谢:

请问您是在什么样的业务场景中使用该能力,交互流程是怎样的,在哪一个环节遇到了问题?方便说明能力不满足可能带来的影响:什么时间用到?是否高频?有无三方库可以做到?若提供该能力,是否会造成大工作量返工?请您注意提供的内容不要包含您或第三方的非公开信息,如给您带来不便,敬请谅解。

HarmonyOS 版 mpchart 和 Android 原版不太一样。

核心问题在于:

setTypeFace() 要的不是字符串字体名,而是 FontFamily 对象。

所以即使你已经在系统里全局注册了字体,Text 能直接 "xxx.ttf" 使用,mpchart 这里也不能直接传字符串。

正确做法是:

先创建 FontFamily,再传给 setTypeFace()

示例:

import { FontFamily } from '@kit.ArkUI'

// 创建字体族
let customFont = new FontFamily('HarmonyOS_Sans_SC')

// 设置给Y轴
yAxis.setTypeFace(customFont)

如果你是通过 Resource 注册字体,例如:

.fontFamily('myFont')

那这里不能直接:

yAxis.setTypeFace('myFont') // ❌ 不行

而是需要:

let font = new FontFamily('myFont')
yAxis.setTypeFace(font)

另外还有一个坑:

有些 mpchart HarmonyOS 移植版本,其实内部并没有真正把 FontFamily 应用到 Canvas/TextPainter 上,所以你即使设置成功,也可能完全不生效。

这个你可以验证:

  • X轴字体是否生效
  • Legend 字体是否生效
  • Description 字体是否生效

如果全部不生效,大概率是库本身没适配完整。

目前 HarmonyOS 上很多 mpchart 三方移植库都存在:

  • 字体不生效
  • 富文本不支持
  • Canvas 字体 fallback
  • 自定义字体渲染丢失

这种问题。

如果确认库本身不支持,通常只有两种方案:

  1. 修改 mpchart 源码
    找到 YAxisRenderer / Renderer 中实际 drawText 的地方,把:

    paint.setTypeface(...)
    

    真正接到 ArkUI 的字体系统。

  2. 放弃 mpchart 默认轴文字
    自己覆盖绘制 Y 轴标签(custom renderer)。

目前这是 HarmonyOS 图表库里比较常见的处理方式。

在HarmonyOS Next中,使用mpchart时,通过YAxis对象的setTextSize()setTypeface()方法可自定义Y轴标签字体。示例:leftAxis.setTextSize(14f); leftAxis.setTypeface(Typeface.DEFAULT_BOLD);。需要预先加载自定义字体文件,再通过Typeface.createFromAsset(context, "font.ttf")设置。

mpchart 中自定义 Y 轴字体,直接使用字体名称或资源构造 FontFamily 对象传入即可。

// 方式一:使用全局注册的字体名称(必须与 font.registerFont 时的 family 名称一致)
yAxis.setTypeface(new FontFamily("myCustomFont"));

// 方式二:使用资源引用(fonts 目录下的资源)
yAxis.setTypeface(new FontFamily($r('app.font.my_custom_font')));

确保字体文件已放在 src/main/resources/base/font/ 目录,或通过 font.registerFont() 注册并指定了 familyNameFontFamily 的构造器可直接接收 stringResource,不必再通过其他手段转换。

回到顶部