想精确控制字体的字重?TypefaceArguments 让你配置字体变体

你有没有注意过,很多字体其实不只是"粗体"和"细体"两种选择?像一些现代字体(比如 HarmonyOS Sans)支持连续的字重变化——从极细(Thin,100)到极粗(Black,900),中间有很多档位。在 HarmonyOS 的 drawing 模块里,TypefaceArguments 就是用来配置这些字体变体参数的。

TypefaceArguments 是什么?

下面是使用 TypefaceArguments 配置字重的完整流程:

加载基础字体 Typeface

创建 TypefaceArguments 对象

调用 addVariation 设置 wght 字重值

字重值范围

100 Thin 极细

400 Normal 常规

700 Bold 粗体

900 Black 极粗

调用 typeface.makeFromCurrent 创建变体

将变体 Typeface 设置到 Font

用该 Font 绘制指定字重的文字

简单说,TypefaceArguments 就是一个"字体属性配置器"。它让你能够指定字体的可变维度参数,比如字重(weight)。

你可能会问:Font 类不是有 enableEmbolden 来加粗吗?有什么区别?

区别在于:enableEmbolden 是"软件模拟加粗",它不管字体文件本身的设计,只是把笔画加粗。而 TypefaceArguments 是"使用字体文件本身的设计",如果字体文件支持多种字重,你可以精确地选择用哪一种。

打个比方:enableEmbolden 就像用粗笔写字,字的骨架还是原来的;TypefaceArguments 就像换了一套专门设计的粗体字模,每个笔画都是精心设计的。

创建 TypefaceArguments

创建一个 TypefaceArguments 对象很简单:

import { drawing } from '@kit.ArkGraphics2D';
let typeFaceArgument = new drawing.TypefaceArguments();

创建出来的是一个空的配置对象,你需要用 addVariation 方法来添加具体的参数。

添加字体变体:addVariation

addVariation 方法用来设置字体的可变维度参数:

import { drawing } from '@kit.ArkGraphics2D';

let typeFaceArgument = new drawing.TypefaceArguments();
typeFaceArgument.addVariation('wght', 10);

这里有两个参数:

axis:维度标签

目前支持的标签是 'wght',代表字重(weight)。这个标签来自 OpenType 字体规范里的可变字体(Variable Fonts)技术。

具体是否支持这个标签,取决于你加载的字体文件。不是所有字体都支持可变字重,你需要查看字体文件的具体支持情况。

value:参数值

对于字重(wght),常用的值有:

名称 说明
100 Thin / Hairline 极细
200 Extra Light / Ultra Light 超细
300 Light
400 Normal / Regular 常规
500 Medium 中等
600 Semi Bold / Demi Bold 半粗
700 Bold
800 Extra Bold / Ultra Bold 超粗
900 Black / Heavy 极粗

注意:这个值必须在字体文件支持的范围内。如果传的值小于字体支持的最小值,会自动使用最小值;如果大于最大值,会自动使用最大值。

怎么使用 TypefaceArguments?

下面是两种使用方式的对比:

加载时指定

基于现有字体创建

使用 TypefaceArguments

使用方式

makeFromFileWithArguments

makeFromCurrent

加载字体文件和参数一步到位

先加载基础字体

创建 Arguments 设置字重

基于基础字体生成变体

获得指定字重的 Typeface

设置到 Font 使用

TypefaceArguments 通常配合 Typeface 的方法来使用。有两种方式:

方式一:加载字体时指定参数

import { RenderNode } from '@kit.ArkUI';
import { drawing } from '@kit.ArkGraphics2D';

class TextRenderNode extends RenderNode {
  async draw(context: DrawContext) {
    const canvas = context.canvas;
    let font = new drawing.Font();
    let str = "/system/fonts/HarmonyOS_Sans_Italic.ttf";
    let typeFaceArgument = new drawing.TypefaceArguments();
    const myTypeFace = drawing.Typeface.makeFromFileWithArguments(str, typeFaceArgument);
    font.setTypeface(myTypeFace);
    const textBlob = drawing.TextBlob.makeFromString("Hello World", font, drawing.TextEncoding.TEXT_ENCODING_UTF8);
    canvas.drawTextBlob(textBlob, 60, 100);
  }
}

Typeface.makeFromFileWithArgumentsTypeface.makeFromRawFileWithArguments 在加载字体文件的同时指定参数。

方式二:基于现有字体创建变体

import { RenderNode } from '@kit.ArkUI';
import { drawing } from '@kit.ArkGraphics2D';

class TextRenderNode extends RenderNode {
  async draw(context: DrawContext) {
    const canvas = context.canvas;
    let typeArguments = new drawing.TypefaceArguments();
    typeArguments.addVariation("wght", 100);
    const myTypeFace = drawing.Typeface.makeFromFile("/system/fonts/HarmonyOS_Sans_SC.ttf");
    const typeFace1 = myTypeFace.makeFromCurrent(typeArguments);
    let font = new drawing.Font();
    font.setTypeface(typeFace1);
    const textBlob = drawing.TextBlob.makeFromString("Hello World", font, drawing.TextEncoding.TEXT_ENCODING_UTF8);
    canvas.drawTextBlob(textBlob, 60, 100);
  }
}

这段代码先加载了 HarmonyOS_Sans_SC.ttf,然后用 makeFromCurrent 基于它创建了一个字重为 100(极细)的变体。

实际应用场景

场景一:标题和正文使用不同字重

做文章阅读 APP 时,标题用粗字重,正文用常规字重:

// 加载字体
let typeface = drawing.Typeface.makeFromFile("/system/fonts/HarmonyOS_Sans_SC.ttf");

// 标题:字重 700(粗体)
let titleArgs = new drawing.TypefaceArguments();
titleArgs.addVariation("wght", 700);
let titleTypeface = typeface.makeFromCurrent(titleArgs);
let titleFont = new drawing.Font();
titleFont.setTypeface(titleTypeface);
titleFont.setSize(28);

// 正文:字重 400(常规)
let bodyArgs = new drawing.TypefaceArguments();
bodyArgs.addVariation("wght", 400);
let bodyTypeface = typeface.makeFromCurrent(bodyArgs);
let bodyFont = new drawing.Font();
bodyFont.setTypeface(bodyTypeface);
bodyFont.setSize(16);

场景二:渐变字重效果

想做一个字重从细到粗的渐变效果?你可以创建多个不同字重的 Typeface:

let baseTypeface = drawing.Typeface.makeFromFile("/system/fonts/HarmonyOS_Sans_SC.ttf");

let weights = [100, 200, 300, 400, 500, 600, 700, 800, 900];
let fonts: drawing.Font[] = [];

for (let w of weights) {
  let args = new drawing.TypefaceArguments();
  args.addVariation("wght", w);
  let tf = baseTypeface.makeFromCurrent(args);
  let f = new drawing.Font();
  f.setTypeface(tf);
  f.setSize(24);
  fonts.push(f);
}

// 然后用这些不同字重的 font 逐个绘制文字,形成渐变效果

场景三:根据用户偏好调整字重

有些用户喜欢看粗一点的文字,有些喜欢细一点的。你可以让用户在设置里选择字重偏好:

function createFontWithWeight(weight: number): drawing.Font {
  let baseTypeface = drawing.Typeface.makeFromFile("/system/fonts/HarmonyOS_Sans_SC.ttf");
  let args = new drawing.TypefaceArguments();
  args.addVariation("wght", weight);
  let tf = baseTypeface.makeFromCurrent(args);
  let font = new drawing.Font();
  font.setTypeface(tf);
  font.setSize(16);
  return font;
}

// 用户选择的字重(100-900)
let userPreferredWeight = 500;
let font = createFontWithWeight(userPreferredWeight);

场景四:数据可视化中的文字标注

在做图表时,不同重要级别的标注可能需要不同的字重:

let baseTypeface = drawing.Typeface.makeFromFile("/system/fonts/HarmonyOS_Sans_SC.ttf");

// 图表标题:字重 700
let titleArgs = new drawing.TypefaceArguments();
titleArgs.addVariation("wght", 700);
let titleTypeface = baseTypeface.makeFromCurrent(titleArgs);

// 坐标轴标签:字重 400
let labelArgs = new drawing.TypefaceArguments();
labelArgs.addVariation("wght", 400);
let labelTypeface = baseTypeface.makeFromCurrent(labelArgs);

// 辅助说明:字重 300
let captionArgs = new drawing.TypefaceArguments();
captionArgs.addVariation("wght", 300);
let captionTypeface = baseTypeface.makeFromCurrent(captionArgs);

注意事项

  1. API 版本:TypefaceArguments 从 API version 20 开始支持。

  2. 字体文件必须支持可变字重:不是所有字体都支持 wght 标签。你需要确认你使用的字体文件是否是可变字体(Variable Font)。如果字体不支持,设置的字重参数不会生效。

  3. 值的范围:传入的值必须在字体文件支持的范围内。超出范围的值会被自动截断到最小或最大值。

  4. 性能考虑:每次调用 makeFromCurrent 都会创建一个新的 Typeface 对象。如果你需要频繁切换字重,建议把常用的字重变体缓存起来。

  5. 物理像素:和其他 drawing 对象一样,使用物理像素单位。

  6. 线程安全:单线程模型,需要自己管理线程安全。

小结

TypefaceArguments 是一个专门用来配置字体变体参数的工具类。目前它主要支持设置字重(wght),让你能够精确控制文字的粗细程度。

和 Font 的 enableEmbolden 不同,TypefaceArguments 使用的是字体文件本身的设计,效果更自然、更专业。如果你的 APP 需要精细的字重控制,TypefaceArguments 是更好的选择。

记住它是从 API version 20 开始支持的,而且需要字体文件本身支持可变字重才能生效。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐