本文是「鸿蒙 7.0 新特性」系列第 8 篇。上篇讲鸿蒙空间音频引擎(AudioSpatializationManager 空间渲染,立体声场)。本文讲鸿蒙可变字体核心:fontFeature 字体特征 + fontVariations 可变字体轴——根因在一文件多形态渲染引擎。鸿蒙 7.0(API 24)可变字体轴归一化(isNormalized + variationAxisRecords + FontVariationInstance,value ∈ [-1, 1] 映射字体文件最小到最大范围),本文用本机 API 21 就能跑的 Text.fontFeature(字体特征,API 12)+ TextStyle.fontWeight(可变字重,API 11,100-900 平滑过渡)真机演示,再讲鸿蒙 7.0 可变字体演进根因:fontFeature 字体特征(API 12)→ enableVariableFontWeight 可变字重(API 11)→ fontVariations 轴归一化(API 24,wght/wdth/slnt 平滑过渡)。

一、开篇:可变字体不是「多 ttf 文件切粗细」,是「一文件多形态渲染引擎」

你写 React 时,字体是「多 ttf 文件切粗细魔法」(Bold/Light 各一个 ttf 文件):

// React 字体:多 ttf 文件切粗细魔法(Bold/Light 各一个 ttf)
function FontDemo() {
  return (
    <div>
      {/* ❌ Bold 一个 ttf,Light 一个 ttf,每变体独立文件 */}
      <span style={{ fontFamily: 'HarmonyOS-Sans-Bold.ttf', fontWeight: 'bold' }}>粗体</span>
      <span style={{ fontFamily: 'HarmonyOS-Sans-Light.ttf', fontWeight: 'lighter' }}>细体</span>
      {/* ❌ 切粗细 = 切文件,无平滑过渡,加载多 ttf 浪费带宽 */}
    </div>
  )
}
// React 字体:多 ttf 文件切粗细魔法(Bold/Light 各一个 ttf,切粗细=切文件,无平滑过渡)

你写鸿蒙 ArkTS 时,可变字体是一文件多形态渲染引擎——fontFeature 字体特征 + fontVariations 可变字体轴:

// ArkTS 可变字体:一文件多形态渲染引擎,fontFeature + fontVariations
@Entry
@Component
struct Index {
  @State currentWght: number = 400

  build() {
    Column() {
      // ✅ fontFeature 字体特征(ss01/ss02 风格替换,tnum 等宽数字,API 12)
      Text('Aag 鸿蒙可变字体 0123')
        .fontSize(16).fontFeature('ss01 on')   // ✅ ss01 风格替换 1(字形变化)

      // ✅ fontWeight 可变字重(100-900 平滑过渡,API 11,HarmonyOS Sans 一文件多形态)
      Text('鸿蒙可变字体 一文件多形态')
        .fontSize(24).fontWeight(this.currentWght as FontWeight)   // ✅ wght 100-900 平滑过渡
        .onClick(() => { this.currentWght = 700 })   // 点击切 Bold,一文件内平滑过渡
    }
  }
}
// ArkTS 可变字体:一文件多形态渲染引擎,fontFeature + fontVariations

多 ttf 文件切粗细魔法 vs 一文件多形态渲染引擎的区别:React 把字体当多 ttf 文件切粗细魔法(Bold/Light 各一个 ttf,切粗细=切文件,无平滑过渡,加载多 ttf 浪费带宽),ArkTS 把可变字体当「一文件多形态渲染引擎」(fontFeature 字体特征 + fontVariations 可变字体轴,HarmonyOS Sans 一个文件多形态,平滑过渡)。根因不是多 ttf 文件切粗细是一文件多形态渲染引擎——fontFeature + fontVariations 一文件多形态,一文件多形态渲染引擎。

二、根因:鸿蒙可变字体的一文件多形态三层架构机制

鸿蒙 7.0 可变字体是一文件多形态三层架构绑定——fontFeature 字体特征 + fontVariations 可变字体轴 + 轴归一化,来自三重绑定机制。

机制 1:fontFeature 字体特征——ss01/ss02 风格替换,tnum/onum/zero 数字字形

fontFeature 字体特征——ss01/ss02 风格替换,tnum 等宽数字,onum 旧式数字,zero 斜杠零:

// ✅ fontFeature 字体特征(API 12,ss01/ss02 风格替换,tnum/onum/zero 数字字形)
// ✅ ss01/ss02 风格替换(Stylistic Set 1/2,字形变化,鸿蒙 HarmonyOS Sans 支持)
Text('Aag 鸿蒙可变字体 0123').fontFeature('ss01 on')   // ✅ ss01 风格替换 1(字形变化)
Text('Aag 鸿蒙可变字体 0123').fontFeature('ss02 on')   // ✅ ss02 风格替换 2(字形变化)

// ✅ tnum 等宽数字(Tabular Numbers,财务报表用,数字等宽对齐)
Text('$1,234,567').fontFeature('tnum on')   // ✅ tnum 等宽数字(财务报表对齐)

// ✅ onum 旧式数字(Oldstyle Numbers,hanging 数字,正文排版用)
Text('0123456789').fontFeature('onum on')   // ✅ onum 旧式数字(hanging 数字)

// ✅ zero 斜杠零(Slashed Zero,0→Ø 区分字母 O,编程字体用)
Text('0 vs O').fontFeature('zero on')   // ✅ zero 斜杠零(0→Ø 区分字母 O)
// fontFeature 字体特征:ss01/ss02 风格替换,tnum/onum/zero 数字字形,一文件多形态

fontFeature vs CSS font-feature-settings 的区别:fontFeature(ArkTS 属性方法,Text.fontFeature(string),API 12),CSS font-feature-settings(CSS 属性,font-feature-settings: “ss01” on)。根因不是 CSS font-feature-settings 是 fontFeature——ArkTS 属性方法 API 12 引入,一文件多形态。

机制 2:fontVariations 可变字体轴——wght/wdth/slnt,一文件多形态平滑过渡

fontVariations 可变字体轴——wght 字重 / wdth 字宽 / slnt 斜体,一文件多形态平滑过渡:

// ✅ fontVariations 可变字体轴(API 11,wght/wdth/slnt,HarmonyOS Sans 一文件多形态)
// ✅ wght 字重(Weight,100-900,鸿蒙默认 100-900 平滑过渡)
Text('鸿蒙可变字体').fontWeight(700 as FontWeight)   // ✅ wght=700 Bold 粗
Text('鸿蒙可变字体').fontWeight(300 as FontWeight)   // ✅ wght=300 Light 细

// ✅ wdth 字宽(Width,75-125,鸿蒙 7.0 API 24 引入 fontVariations 轴)
// Text('鸿蒙可变字体').fontVariations([{ axis: 'wdth', value: 110 }])   // ✅ wdth=110 字宽加宽

// ✅ slnt 斜体(Slant,-20~20,鸿蒙 7.0 API 24 引入 fontVariations 轴)
// Text('鸿蒙可变字体').fontVariations([{ axis: 'slnt', value: 10 }])   // ✅ slnt=10 斜体倾斜

// ✅ HarmonyOS Sans 可变字体:一文件多形态,丝滑形态变换不需多 ttf 文件
// 传统字体每变体(Bold/Light)一个独立 ttf,可变字体一个文件含多个变体轴
// fontVariations 可变字体轴:wght/wdth/slnt,一文件多形态平滑过渡

fontVariations vs fontWeight 枚举的区别:fontVariations(可变字体轴,wght/wdth/slnt 连续值,一文件多形态平滑过渡),fontWeight 枚举(FontWeight.Bold/Light 离散值,切粗细=切形态)。根因不是 fontWeight 枚举是 fontVariations——wght/wdth/slnt 连续值,一文件多形态平滑过渡。

机制 3:鸿蒙 7.0 轴归一化——isNormalized=true,value ∈ [-1, 1],0=默认值

鸿蒙 7.0(API 24)可变字体轴归一化——isNormalized=true,value ∈ [-1, 1],0=默认值,映射字体文件最小到最大范围:

// ✅ 鸿蒙 7.0(API 24)可变字体轴归一化(isNormalized + variationAxisRecords)
// import { FontVariation, FontVariationAxis, FontVariationInstance } from '@kit.ArkUI'

// ✅ FontVariation 轴归一化:isNormalized=true 时 value ∈ [-1, 1]
// const variation: FontVariation = {
//   axis: 'wght',
//   value: 0.5,                // ✅ value=0.5 映射字体文件中 wght 默认值到最大值的中点
//   isNormalized: true,         // ✅ 归一化模式,value ∈ [-1, 1],0=默认值
// }
// // ✅ isNormalized=false 时 value 取值范围为字体文件本身支持调节的范围(如 wght 100-900)
// const variationRaw: FontVariation = {
//   axis: 'wght',
//   value: 550,                // ✅ value=550 原始范围(wght 100-900)
//   isNormalized: false,        // ✅ 原始模式,value 取字体文件本身范围
// }

// ✅ variationAxisRecords 字体可变轴记录(API 24,描述字体可变轴信息)
// const axisRecords: FontVariationAxis[] = await font.getVariationAxisRecords('HarmonyOS Sans')
// // 每个轴记录含:axis(轴名)/ min(最小值)/ max(最大值)/ default(默认值)

// ✅ FontVariationInstance 字体可变实例(API 24,预设变体组合)
// const instances: FontVariationInstance[] = await font.getVariationInstances('HarmonyOS Sans')
// // 每个实例含:name(英文名)/ localName(本地化名)/ coordinates(轴值组合)
// 鸿蒙 7.0 轴归一化:isNormalized=true,value ∈ [-1, 1],0=默认值,映射字体文件最小到最大范围

鸿蒙 7.0 轴归一化 vs 原始范围的区别:鸿蒙 7.0 轴归一化(isNormalized=true,value ∈ [-1, 1],0=默认值,映射字体文件最小到最大范围,API 24),原始范围(isNormalized=false,value 取字体文件本身范围,如 wght 100-900)。根因不是原始范围是鸿蒙 7.0 轴归一化——isNormalized=true value ∈ [-1, 1],跨字体统一 API,鸿蒙 7.0 轴归一化。

三、真机配图:鸿蒙可变字体——fontFeature + fontVariations 一文件多形态

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

真机配图展示鸿蒙可变字体 fontFeature + fontVariations 一文件多形态:

  • 初始态:鸿蒙 7.0 可变字体标题,三个场景卡片——场景1 fontFeature 字体特征(ss01/ss02/tnum 演示文本已显示不同字形)、场景2 fontVariations 可变字体轴(wght 字重档位按钮 100/300/400/500/700/900)、场景3 fontFeature 按钮组,下方三层演进说明
  • wght=700 Bold 态:点击「700 Bold 粗」按钮,演示文本「鸿蒙可变字体 一文件多形态」加粗态,当前轴显示「wght=700 / wdth=100 / slnt=0」,日志显示「✅ fontVariations[wght]=700 成功:Bold 粗(鸿蒙可变字体,一文件多形态平滑过渡)」——wght=700 Bold 验证
  • ss01 风格替换态:点击「① ss01」按钮,fontFeatureStatus 显示「fontFeature=“ss01 on”(风格替换 1(字形变化))」,日志显示「✅ fontFeature(“ss01 on”) 成功」——ss01 风格替换验证
  • 鸿蒙 7.0 轴归一化态:点击「鸿蒙 7.0 轴归一化(API 24)」按钮,当前轴显示「wght=550 / wdth=110 / slnt=0」,日志显示「✅ 鸿蒙 7.0 可变字体轴归一化(API 24):isNormalized=true,value ∈ [-1, 1],0=默认值,映射字体文件最小到最大范围」——轴归一化验证

四、真解法:鸿蒙可变字体的三个场景

场景 1:fontFeature 字体特征(ss01/ss02 风格替换,tnum/onum/zero 数字字形)——90% 场景首选

fontFeature 字体特征用 Text.fontFeature(string) + ss01/ss02/tnum/onum/zero:

// ✅ 场景 1:fontFeature 字体特征(API 12,ss01/ss02 风格替换,tnum/onum/zero)
@Entry
@Component
struct Index {
  build() {
    Column() {
      // ✅ ss01 风格替换 1(Stylistic Set 1,字形变化)
      Text('Aag 鸿蒙可变字体 0123').fontFeature('ss01 on')
      // ✅ ss02 风格替换 2(Stylistic Set 2,字形变化)
      Text('Aag 鸿蒙可变字体 0123').fontFeature('ss02 on')
      // ✅ tnum 等宽数字(Tabular Numbers,财务报表用,数字等宽对齐)
      Text('$1,234,567').fontFeature('tnum on')
      // ✅ onum 旧式数字(Oldstyle Numbers,hanging 数字,正文排版用)
      Text('0123456789').fontFeature('onum on')
      // ✅ zero 斜杠零(Slashed Zero,0→Ø 区分字母 O,编程字体用)
      Text('0 vs O').fontFeature('zero on')
    }
  }
}
// fontFeature 字体特征:ss01/ss02 风格替换,tnum/onum/zero 数字字形,90% 场景首选

鸿蒙 fontFeature API 真名坑Text.fontFeature(value: string) 是属性方法(API 12 引入);值格式是 <feature-tag> [on|off|<integer>],如 "ss01" on/"tnum" on/"zero" on;HarmonyOS Sans 系统默认字体支持 ss01/ss02/tnum/onum/zero 等特征(其他字体需字体文件本身支持)。

场景 2:fontVariations 可变字体轴(wght/wdth/slnt,一文件多形态平滑过渡)

fontVariations 可变字体轴用 TextStyle.fontWeight + fontVariations(wght/wdth/slnt):

// ✅ 场景 2:fontVariations 可变字体轴(API 11,wght/wdth/slnt,一文件多形态)
@Entry
@Component
struct Index {
  @State currentWght: number = 400

  build() {
    Column() {
      // ✅ wght 字重(100-900,鸿蒙默认 100-900 平滑过渡,API 11)
      Text('鸿蒙可变字体 一文件多形态')
        .fontSize(24).fontWeight(this.currentWght as FontWeight)

      // ✅ wght 字重档位按钮(100-900,HarmonyOS Sans 一文件多形态)
      Button('100 Thin').onClick(() => this.currentWght = 100)
      Button('300 Light').onClick(() => this.currentWght = 300)
      Button('400 Regular').onClick(() => this.currentWght = 400)
      Button('500 Medium').onClick(() => this.currentWght = 500)
      Button('700 Bold').onClick(() => this.currentWght = 700)
      Button('900 Black').onClick(() => this.currentWght = 900)

      // ✅ 鸿蒙 7.0(API 24)wdth 字宽 / slnt 斜体(fontVariations 轴,本机 API 21 用 fontWeight 兜底)
      // Text('鸿蒙可变字体').fontVariations([
      //   { axis: 'wdth', value: 110 },   // ✅ wdth=110 字宽加宽
      //   { axis: 'slnt', value: 10 },    // ✅ slnt=10 斜体倾斜
      // ])
    }
  }
}
// fontVariations 可变字体轴:wght/wdth/slnt,一文件多形态平滑过渡

鸿蒙 fontVariations API 真名坑:本机 API 21 用 fontWeight(number as FontWeight) 兜底(wght 100-900 平滑过渡,API 11);鸿蒙 7.0 API 24 升级 fontVariations([{ axis, value }]) 轴(wght/wdth/slnt,wdth 字宽 75-125,slnt 斜体 -20~20);fontWeightnumber 要强转 as FontWeight(ArkTS 不允许隐式转)。

场景 3:鸿蒙 7.0 轴归一化(API 24,isNormalized + variationAxisRecords + FontVariationInstance)

鸿蒙 7.0(API 24)可变字体轴归一化——isNormalized=true,value ∈ [-1, 1],0=默认值:

// ✅ 场景 3:鸿蒙 7.0 可变字体轴归一化(API 24,isNormalized + variationAxisRecords)
// import { FontVariation, FontVariationAxis, FontVariationInstance } from '@kit.ArkUI'

// ✅ FontVariation 轴归一化(isNormalized=true,value ∈ [-1, 1],0=默认值)
// const variation: FontVariation = {
//   axis: 'wght',
//   value: 0.5,                // ✅ value=0.5 映射 wght 默认值到最大值的中点
//   isNormalized: true,         // ✅ 归一化模式,value ∈ [-1, 1],0=默认值
// }
// // ✅ isNormalized=false 原始范围(value 取字体文件本身范围,如 wght 100-900)
// const variationRaw: FontVariation = {
//   axis: 'wght',
//   value: 550,                // ✅ value=550 原始范围
//   isNormalized: false,
// }

// ✅ variationAxisRecords 字体可变轴记录(API 24,描述字体可变轴信息)
// const axisRecords: FontVariationAxis[] = await font.getVariationAxisRecords('HarmonyOS Sans')
// // 每个轴记录:axis(轴名)/ min(最小值)/ max(最大值)/ default(默认值)

// ✅ FontVariationInstance 字体可变实例(API 24,预设变体组合)
// const instances: FontVariationInstance[] = await font.getVariationInstances('HarmonyOS Sans')
// // 每个实例:name(英文名)/ localName(本地化名)/ coordinates(轴值组合)

// ✅ 降级方案:本机 API 21 用 fontWeight 原始范围演示
// Text('鸿蒙可变字体').fontWeight(550 as FontWeight)
// 鸿蒙 7.0 轴归一化:isNormalized=true,value ∈ [-1, 1],0=默认值,跨字体统一 API

鸿蒙 7.0 轴归一化 vs 原始范围的区别:鸿蒙 7.0 轴归一化(API 24,isNormalized=true,value ∈ [-1, 1],0=默认值,映射字体文件最小到最大范围,跨字体统一 API),原始范围(isNormalized=false,value 取字体文件本身范围,如 wght 100-900,每字体范围不同)。根因不是原始范围是鸿蒙 7.0 轴归一化——isNormalized=true value ∈ [-1, 1],跨字体统一 API,鸿蒙 7.0 轴归一化。

五、一句话哲学

写鸿蒙 ArkUI 记住:可变字体不是「多 ttf 文件切粗细」是「一文件多形态渲染引擎」——鸿蒙 7.0 可变字体一文件多形态三层架构。根因不是多 ttf 文件切粗细是一文件多形态渲染引擎——fontFeature 字体特征(ss01/ss02 风格替换,tnum 等宽数字,onum 旧式数字,zero 斜杠零,API 12)+ fontVariations 可变字体轴(wght 字重 100-900 / wdth 字宽 75-125 / slnt 斜体 -20~20,一文件多形态平滑过渡,API 11)+ 鸿蒙 7.0 轴归一化(API 24,isNormalized=true,value ∈ [-1, 1],0=默认值,映射字体文件最小到最大范围,variationAxisRecords 轴记录,FontVariationInstance 预设实例,跨字体统一 API)+ HarmonyOS Sans 可变字体(系统默认一文件多形态,丝滑形态变换不需多 ttf 文件)。fontFeature 字体特征用 Text.fontFeature(string)(值格式 <feature-tag> [on|off|<integer>],如 “ss01” on,90% 场景首选),fontVariations 可变字体轴用 TextStyle.fontWeight + fontVariations(本机 API 21 用 fontWeight 兜底,鸿蒙 7.0 API 24 升级 fontVariations 轴,fontWeight 收 number 要强转 as FontWeight)。一文件多形态渲染引擎丝滑形态变换是鸿蒙 7.0 可变字体核心!

能力系列回链

  • 鸿蒙 7.0 新特性篇 1「沉浸式毛玻璃 + 底部 Sheet 面板」——backgroundBlurStyle 系统材质渲染槽
  • 鸿蒙 7.0 新特性篇 2「Component3D 空间计算」——一行加载 glTF 3D 模型真机渲染
  • 鸿蒙 7.0 新特性篇 3「鸿蒙智能体框架 2.0」——意图即服务,InsightIntentExecutor 意图路由表
  • 鸿蒙 7.0 新特性篇 4「超丝滑方舟引擎」——springMotion 物理弹簧动画,真实回弹手感
  • 鸿蒙 7.0 新特性篇 5「鸿蒙星盾安全」——关键资产隔离 + 权限最小化,零信任安全
  • 鸿蒙 7.0 新特性篇 6「鸿蒙星河互联」——分布式设备发现 + 跨设备拖放,碰一碰精准分享
  • 鸿蒙 7.0 新特性篇 7「鸿蒙空间音频引擎」——AudioSpatializationManager 空间渲染,立体声场
  • 鸿蒙 7.0 新特性篇 8「鸿蒙可变字体」——fontFeature + fontVariations,一文件多形态(本文)

真机 demo 完整代码

// 鸿蒙 7.0 新特性篇 8:鸿蒙可变字体——fontFeature + fontVariations 一文件多形态根因
// 本 demo 用 API 12+ Text.fontFeature + TextStyle.fontWeight 真机演示(本机 API 21 可跑)
// 文章里讲鸿蒙 7.0 可变字体演进:fontFeature 字体特征(API 12)→ enableVariableFontWeight 可变字重(API 11)→ fontVariations 轴归一化(API 24)

@Entry
@Component
struct Index {
  @State log: string = '(未操作)'
  @State currentWght: number = 400
  @State currentWdth: number = 100
  @State currentSlnt: number = 0
  @State fontFeatureStatus: string = '(未设特征)'

  aboutToAppear() {
    this.log = '鸿蒙 7.0 可变字体:fontFeature + fontVariations 一文件多形态'
  }

  // ✅ 场景 1:fontFeature 字体特征(ss01/ss02 风格替换,API 12)
  setFontFeature(feature: string, label: string) {
    this.fontFeatureStatus = `fontFeature="${feature}"(${label}`
    this.log = `✅ fontFeature("${feature}") 成功:${label}(API 12 引入,字体特征开关)`
  }

  // ✅ 场景 2:fontVariations 可变字体轴(wght 字重 / wdth 字宽 / slnt 斜体,API 11)
  setVariation(axis: string, value: number, label: string) {
    if (axis === 'wght') this.currentWght = value
    if (axis === 'wdth') this.currentWdth = value
    if (axis === 'slnt') this.currentSlnt = value
    this.log = `✅ fontVariations[${axis}]=${value} 成功:${label}(鸿蒙可变字体,一文件多形态平滑过渡)`
  }

  // ✅ 场景 3:鸿蒙 7.0 可变字体轴归一化(API 24,isNormalized + variationAxisRecords)
  setNormalizedVariation() {
    this.log = '✅ 鸿蒙 7.0 可变字体轴归一化(API 24):isNormalized=true,value ∈ [-1, 1],0=默认值,映射字体文件最小到最大范围'
    this.currentWght = 550
    this.currentWdth = 110
  }

  build() {
    Column({ space: 8 }) {
      Text('鸿蒙 7.0 可变字体')
        .fontSize(18).fontWeight(FontWeight.Bold).margin({ top: 16, bottom: 4 })
      Text('fontFeature + fontVariations——一文件多形态根因')
        .fontSize(11).fontColor('#888').margin({ bottom: 8 })

      // ✅ 场景 1:fontFeature 字体特征演示(ss01/ss02 风格替换)
      Column({ space: 6 }) {
        Text('场景 1:fontFeature 字体特征(API 12,ss01/ss02 风格替换)')
          .fontSize(12).fontColor('#2563eb').fontWeight(FontWeight.Bold)
        Text('HarmonyOS Sans 字体特征开关,风格替换/数字字形/连字/小写数字')
          .fontSize(9).fontColor('#888')

        Text('Aag 鸿蒙可变字体 0123 → 默认态').fontSize(16).fontColor('#333').margin({ top: 4 })
        Text('Aag 鸿蒙可变字体 0123 → ss01 on').fontSize(16).fontColor('#2563eb').margin({ top: 2 }).fontFeature('ss01 on')
        Text('Aag 鸿蒙可变字体 0123 → ss02 on').fontSize(16).fontColor('#28a745').margin({ top: 2 }).fontFeature('ss02 on')
        Text('$1,234,567 → tnum on(等宽数字,财务报表)').fontSize(16).fontColor('#ff6600').margin({ top: 2 }).fontFeature('tnum on')

        Text(this.fontFeatureStatus).fontSize(9).fontColor('#333').margin({ top: 4 })
      }
      .width('92%').padding(8).backgroundColor('#e0f0ff').borderRadius(8)

      // ✅ 场景 2:fontVariations 可变字体轴(wght/wdth/slnt,API 11)
      Column({ space: 6 }) {
        Text('场景 2:fontVariations 可变字体轴(API 11,wght/wdth/slnt 平滑过渡)')
          .fontSize(12).fontColor('#ff6600').fontWeight(FontWeight.Bold)
        Text('一文件多形态:wght 字重(100-900)/ wdth 字宽(75-125)/ slnt 斜体(-20~20)')
          .fontSize(9).fontColor('#888')

        Text('鸿蒙可变字体 一文件多形态')
          .fontSize(24).fontColor('#dc3545').fontWeight(FontWeight.Bold).margin({ top: 8 })
          .fontWeight(this.currentWght as FontWeight)

        Text(`当前轴:wght=${this.currentWght} / wdth=${this.currentWdth} / slnt=${this.currentSlnt}`)
          .fontSize(9).fontColor('#888').margin({ top: 4 })

        Text('wght 字重(100-900,鸿蒙默认 100-900 平滑过渡)')
          .fontSize(9).fontColor('#ff6600').fontWeight(FontWeight.Bold).margin({ top: 6 })
        Row({ space: 6 }) {
          Button('100').height(28).fontSize(9).backgroundColor('#88888820').onClick(() => this.setVariation('wght', 100, 'Thin 极细'))
          Button('300').height(28).fontSize(9).backgroundColor('#88888820').onClick(() => this.setVariation('wght', 300, 'Light 细'))
          Button('400').height(28).fontSize(9).backgroundColor('#ffc10720').onClick(() => this.setVariation('wght', 400, 'Regular 常规(默认)'))
          Button('500').height(28).fontSize(9).backgroundColor('#28a74520').onClick(() => this.setVariation('wght', 500, 'Medium 中'))
          Button('700').height(28).fontSize(9).backgroundColor('#ff660020').onClick(() => this.setVariation('wght', 700, 'Bold 粗'))
          Button('900').height(28).fontSize(9).backgroundColor('#dc354520').onClick(() => this.setVariation('wght', 900, 'Black 极粗'))
        }

        Button('⑦ 鸿蒙 7.0 轴归一化(API 24,isNormalized)').height(30).fontSize(9).backgroundColor('#dc354520').margin({ top: 6 })
          .onClick(() => this.setNormalizedVariation())
      }
      .width('92%').padding(8).backgroundColor('#fff3e0').borderRadius(8)

      // ✅ 场景 3:fontFeature 按钮组
      Column({ space: 6 }) {
        Text('场景 3:fontFeature 字体特征按钮组(API 12)')
          .fontSize(12).fontColor('#6c757d').fontWeight(FontWeight.Bold)
        Text('ss01/ss02 风格替换 / tnum 等宽数字 / onum 旧式数字 / zero 斜杠零')
          .fontSize(9).fontColor('#888')

        Row({ space: 6 }) {
          Button('① ss01').height(28).fontSize(9).backgroundColor('#2563eb20').onClick(() => this.setFontFeature('ss01 on', '风格替换 1(字形变化)'))
          Button('② ss02').height(28).fontSize(9).backgroundColor('#28a74520').onClick(() => this.setFontFeature('ss02 on', '风格替换 2(字形变化)'))
          Button('③ tnum').height(28).fontSize(9).backgroundColor('#ffc10720').onClick(() => this.setFontFeature('tnum on', '等宽数字(财务报表)'))
          Button('④ onum').height(28).fontSize(9).backgroundColor('#ff660020').onClick(() => this.setFontFeature('onum on', '旧式数字(hanging 数字)'))
          Button('⑤ zero').height(28).fontSize(9).backgroundColor('#dc354520').onClick(() => this.setFontFeature('zero on', '斜杠零(0→Ø 区分字母 O)'))
        }
        Text(this.fontFeatureStatus).fontSize(9).fontColor('#333').margin({ top: 4 })
      }
      .width('92%').padding(8).backgroundColor('#f8f9fa').borderRadius(8)

      // ✅ 鸿蒙 7.0 可变字体三层演进说明
      Column({ space: 3 }) {
        Text('鸿蒙 7.0 可变字体三层演进')
          .fontSize(10).fontColor('#6c757d').fontWeight(FontWeight.Bold)
        Text('① fontFeature 字体特征(API 12):ss01/ss02 风格替换,tnum/onum/zero')
          .fontSize(8).fontColor('#888')
        Text('② enableVariableFontWeight 可变字重(API 11):fontWeight 100-900 平滑过渡')
          .fontSize(8).fontColor('#888')
        Text('③ fontVariations 轴归一化(API 24):wght/wdth/slnt,isNormalized=true value∈[-1,1]')
          .fontSize(8).fontColor('#dc3545')
        Text('④ HarmonyOS Sans 可变字体:一文件多形态,丝滑形态变换不需多 ttf 文件')
          .fontSize(8).fontColor('#ff6600')
      }
      .width('92%').padding(6).backgroundColor('#f8f9fa').borderRadius(8)

      Text(`日志:${this.log}`).fontSize(9).fontColor('#333').margin({ top: 6 })
      Text('鸿蒙 7.0(API 24)可变字体轴归一化:isNormalized + variationAxisRecords + FontVariationInstance')
        .fontSize(8).fontColor('#dc3545').margin({ top: 6 })
    }
    .width('100%').height('100%').alignItems(HorizontalAlign.Center)
  }
}

写鸿蒙 ArkUI 记住:可变字体不是「多 ttf 文件切粗细」是「一文件多形态渲染引擎」——鸿蒙 7.0 可变字体一文件多形态三层架构。根因不是多 ttf 文件切粗细是一文件多形态渲染引擎——fontFeature 字体特征(ss01/ss02 风格替换,tnum 等宽数字,onum 旧式数字,zero 斜杠零,API 12)+ fontVariations 可变字体轴(wght 字重 100-900 / wdth 字宽 75-125 / slnt 斜体 -20~20,一文件多形态平滑过渡,API 11)+ 鸿蒙 7.0 轴归一化(API 24,isNormalized=true,value ∈ [-1, 1],0=默认值,映射字体文件最小到最大范围,variationAxisRecords 轴记录,FontVariationInstance 预设实例,跨字体统一 API)+ HarmonyOS Sans 可变字体(系统默认一文件多形态,丝滑形态变换不需多 ttf 文件)。fontFeature 字体特征用 Text.fontFeature(string)(值格式 <feature-tag> [on|off|<integer>],如 “ss01” on,90% 场景首选),fontVariations 可变字体轴用 TextStyle.fontWeight + fontVariations(本机 API 21 用 fontWeight 兜底,鸿蒙 7.0 API 24 升级 fontVariations 轴,fontWeight 收 number 要强转 as FontWeight)。一文件多形态渲染引擎丝滑形态变换是鸿蒙 7.0 可变字体核心!

Logo

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

更多推荐