复杂文本绘制与显示（ArkTS）
================

在进行文本绘制时，可以通过选择合适的字体、大小和颜色完成简单文本的绘制与显示；此外，还支持通过设置其他丰富的样式、语言、段落等进行复杂文本的绘制。

复杂文本绘制主要包含以下几个场景：

*   多语言文本绘制与显示
    
*   多行文本绘制与显示
    
*   多样式文本绘制与显示
    

#### 多语言文本绘制与显示

多语言支持是全球化应用的基础。多语言文本绘制需要支持不同语言的字符集及其独特的显示需求，例如右到左语言（如阿拉伯语）或竖排文本（如中文）。开发者需要理解不同语言的渲染特性，确保文本的正确显示。

在多语言文本使用的场景下，主要通过指定[TextStyle](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-graphics-text#textstyle)文本样式中的**locale**字段来实现，可直接通过locale字段的值优先匹配对应字体，跳过遍历列表匹配字体的过程，从而降低匹配时间和内存使用。

#### \[h2\]开发步骤

1.  通过context获取到Canvas画布对象。
    
    // 绘制代码逻辑写在这里
    let canvas = context.canvas;
    
2.  初始化文本样式。
    
    let myTextStyle: text.TextStyle = {
      color: {
        alpha: 255,
        red: 255,
        green: 0,
        blue: 0
      },
      fontSize: 50,
      // 设置语言偏好为简体中文
      locale: 'zh-Hans'
    };
    
3.  初始化段落样式。
    
    let myParagraphStyle: text.ParagraphStyle = {
      textStyle: myTextStyle,
    };
    
4.  初始化段落对象，并添加文本。
    
    let fontCollection = text.FontCollection.getGlobalInstance();
    let paragraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection);
    // 更新文本样式
    paragraphBuilder.pushStyle(myTextStyle);
    // 添加文本
    paragraphBuilder.addText('你好，世界');
    
5.  排版段落并进行文本绘制。
    
    // 生成段落
    let paragraph = paragraphBuilder.build();
    // 布局
    paragraph.layoutSync(1250);
    // 绘制文本
    paragraph.paint(canvas, 10, 0);
    

#### \[h2\]效果展示

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/9d/v3/Bn6D5uk_SRWdn5RbB1_LQA/zh-cn_image_0000002594828876.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=1E316F8E7D8A8FCAB29BCACE647839BF8FE21C0684F4EB4BE5B3262080EDC822)

#### 多行文本绘制与显示

多行文本相对于单行文本比较复杂，一般针对多行文本，需要进行文本排版、断词策略设置、文本对齐方式、最大行数限制等，主要通过设置段落样式实现。

#### \[h2\]实现说明

**段落样式**（[ParagraphStyle](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-graphics-text#paragraphstyle)）是对多行文本中每段内容的样式设置，包括断词策略、文本对齐方式、最大行数限制等。开发者可以通过对不同段落进行样式化，以提高文本的可读性和美观性。

#### \[h2\]开发步骤

1.  通过context获取到Canvas画布对象。
    
    // 绘制代码逻辑写在这里
    let canvas = context.canvas;
    
2.  初始化文本样式。
    
    let myTextStyle: text.TextStyle = {
      color: {
        alpha: 255,
        red: 255,
        green: 0,
        blue: 0
      },
      fontSize: 50,
      // 当wordBreak为text.WordBreak.BREAK\_HYPHEN时，需要为段落设置语言偏好，段落会在不同语言偏好下呈现不同的文本断词效果
      locale: 'en-gb'
    };
    
3.  初始化段落样式。
    
    let myParagraphStyle: text.ParagraphStyle = {
      textStyle: myTextStyle,
      // 文本对齐方式
      align: text.TextAlign.LEFT,
      // 最大行数
      maxLines: 3,
      // 断词策略
      wordBreak: text.WordBreak.BREAK\_WORD
    };
    
4.  初始化段落对象，并添加占位符和文本。
    
    let fontCollection = text.FontCollection.getGlobalInstance();
    let paragraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection);
    // 更新文本样式
    paragraphBuilder.pushStyle(myTextStyle);
    // 添加文本
    paragraphBuilder.addText('Hello World Hello World Hello World Hello World Hello World Hello World ' +
      'Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World ' +
      'Hello World Hello World Hello World Hello World Hello World ');
    
5.  排版段落并进行文本绘制。
    
    // 生成段落
    let paragraph = paragraphBuilder.build();
    // 布局
    paragraph.layoutSync(1250);
    // 绘制文本
    paragraph.paint(canvas, 10, 0);
    

#### \[h2\]效果展示

| 段落样式设置（断词策略、文本对齐方式、最大行数限制） | 效果示意 |
| :-- | :-- |
| 文本对齐方式为text.TextAlign.LEFT，最大行数为3，断词策略为text.WordBreak.BREAK\_WORD。 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/12/v3/sV9T_5cVSPWPubkKjUTT4Q/zh-cn_image_0000002625188323.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=4E27FF37B483A9BB892285F39089989DF9F4181F9864E378570FFE983D49E46F) |
| 文本对齐方式为text.TextAlign.RIGHT，最大行数为3，断词策略为text.WordBreak.BREAK\_WORD。 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/df/v3/1jBdpvokRHOZUS5uRaBLgQ/zh-cn_image_0000002625108467.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=4A56FFABFD54F6A342531A0E524D64D261B2AB31BF5B516FFFFA42C7F55A1C6C) |
| 文本对齐方式为text.TextAlign.JUSTIFY，最大行数为10，断词策略为text.WordBreak.BREAK\_WORD。 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/33/v3/pXoNz-nSRj2Ciu6tpuMHPQ/zh-cn_image_0000002594668950.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=BEAFA37006DEC8B9B81A686AF996CB3A4BA6ED378CAA6442AF1AFAB1A156A8F3) |
| 文本对齐方式为text.TextAlign.LEFT，最大行数为3，断词策略为text.WordBreak.BREAK\_ALL。 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/85/v3/Qm_FR8CgTE-_tvj-Mmn7zA/zh-cn_image_0000002594828878.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=3C4B61EF62105D040A0F6924F816D0E2E13E786C27B475B83640C869E85DCBF9) |
| 文本对齐方式为text.TextAlign.LEFT，最大行数为10，断词策略为text.WordBreak.BREAK\_ALL。 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/ea/v3/Yxg8GlSKTuuNgcwKjveITw/zh-cn_image_0000002625188325.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=70F6F117B457D4535DF2DC30F744B6571B432294DE375F21CF3BC1854E34E745) |
| 
文本对齐方式为text.TextAlign.LEFT，最大行数为10，断词策略为text.WordBreak.BREAK\_HYPHEN，

不设置语言偏好。段落无连字符“-”断词效果。

 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/d/v3/-tdRqVSISrKfnW4fWlXUqg/zh-cn_image_0000002625108469.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=6FF192BCE323EABA38ACAE78849775EC2759CA729BDDC2A54FA489778F5B851D) |
| 

文本对齐方式为text.TextAlign.LEFT，最大行数为10，断词策略为text.WordBreak.BREAK\_HYPHEN，

语言偏好为en-gb（英式英语）。段落产生连字符“-”断词效果，并根据语言偏好呈现英式语言环境断词效果。

 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/ea/v3/AwJnejT7Q6SSFbJftpM_4Q/zh-cn_image_0000002594668952.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=4870264A478E02EDF7A3D23E0FF6BD35794557B4A2877AC5273404604A1DE2BA) |
| 

文本对齐方式为text.TextAlign.LEFT，最大行数为10，断词策略为text.WordBreak.BREAK\_HYPHEN，

语言偏好为en-us（美式英语）。段落产生连字符“-”断词效果，并根据语言偏好呈现美式语言环境断词效果。

 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/05/v3/bWnh5BmLThmViPUz79LP6Q/zh-cn_image_0000002594828880.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=8C2DBDF55656D881A960DC1FE01BC2A828982FD6FDC3D5EBE8D79A37528408D4) |

#### 多样式文本绘制与显示

除基本文字、排版属性之外，针对应用中不同文本的设计，开发者可能需要设置使用不同的绘制样式或能力，以凸显对应文本的独特表现或风格，此时可以结合使用多种绘制样式进行文本的渲染。

当前支持的多样式绘制及各绘制样式侧重效果如下：

*   **装饰线样式绘制：** 主要通过不同的线条样式对文本进行装饰，可以使文本更加突出，富有表现力。
    
*   **字体特性绘制：** 主要通过字体的变化，包括粗细、斜体等特性来改变文本的外观，增强文本的可读性和美观性。
    
*   **可变字体绘制：** 对应提供文本在不同的显示环境和设备上灵活调整的能力，可满足更为精细的视觉效果。
    
*   **文本阴影绘制：** 主要通过在文本周围添加阴影效果，以提升文本的层次感和立体感，从而使文本更具吸引力。
    
*   **占位符绘制：** 可以在不确定文本内容时保持文本布局的稳定性，使得文本显示更为流畅和自然。
    
*   **自动间距绘制：** 可以在一些字符混排切换的地方自动添加额外间距，提升阅读体验。
    
*   **垂直对齐：** 调整文本在垂直方向排版位置，提升排版质量。
    
*   **上下标：** 可以将任意字符处理成上标或下标，更精准表达文本含义。
    
*   **高对比度文字绘制：** 主要通过将深色文字变黑、浅色文字变白，增强文本的对比效果。
    
*   **行高调整：** 调整行高可改变文本行的垂直间距，使行间距更松散或更紧凑，显著改善文本垂直截断问题，提高可读性。
    
*   **行间距调整：** 通过调整行间距的方式可以实现行高调整一样的效果，优化阅读体验。
    
*   **省略号样式设置：** 在文本内容超出显示区域时，可以使用省略号截断文本，支持头部、中部、尾部以及多行省略模式。
    
*   **文字换行方式设置：** 文本排版时支持不同的断行策略，可根据场景选择合适的换行方式。
    
*   **行首标点压缩：** 在排版中，通过开启行首标点压缩功能，将行首标点符号进行挤压处理，避免标点占用行首空间，提升排版紧凑度。
    

#### \[h2\]装饰线

装饰线（[Decoration](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-graphics-text#decoration)）是指在文本上方、下方或中间添加的装饰性线条，当前支持上划线、下划线、删除线。

可以通过添加文本装饰线，提升文本的视觉效果和可读性。

使用装饰线需要初始化装饰线样式对象，并添加到文本样式中，从而在文本绘制时生效。

具体使用效果可参见下文[示例一](#示例一装饰线字体特征)。

#### \[h2\]字体特征

**字体特征**（[FontFeature](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-graphics-text#fontfeature)）绘制专注于在文本渲染过程中对字体特性（如粗体、斜体、字体变种等）的处理，允许字体在不同的排版场景下表现出不同的效果，可用于增强文本的表现力，使其更符合设计和阅读需求。

常见的**FontFeature**包含有liga、frac、case等，需要对应的ttf文件支持才能正常使能。

具体使用效果可参见下文[示例一](#示例一装饰线字体特征)。

#### \[h2\]可变字体

**可变字体**（[FontVariation](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-graphics-text#fontvariation)）是一种在一个字体文件中包含多个字形变体的字体格式，允许在一个字体文件内灵活地调整字体的各种属性（如字重、字宽、斜体等）。

与传统字体文件（每种变体需要一个独立的文件）不同，可变字体在一个字体文件中包含多个变体轴，可通过使用可变字体实现文本渲染绘制时的平滑过渡。

具体使用效果可参见下文[示例二](#示例二可变字体文本阴影占位符)。

#### \[h2\]文本阴影

**文本阴影**（[TextShadow](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-graphics-text#textshadow)）为文本提供了深度感，使得文本在背景上更具立体感。通常用于提升文本的视觉吸引力或增强可读性，尤其是在色彩对比度较低的场景下。

其中，TextShadow有三个属性，分别为阴影颜色color、阴影基于当前文本的偏移位置point、阴影半径blurRadius。

使用阴影效果需要在文本样式中设置对应的阴影效果数组，从而在文本绘制时生效。

具体使用效果可参见下文[示例二](#示例二可变字体文本阴影占位符)。

#### \[h2\]占位符

占位符绘制用于处理文本中占位符符号的渲染。

占位符也是用来实现图文混排的关键，是指在实际图像或内容注册之前，用来预先提供或替代某个位置的视觉元素。

具体使用效果可参见下文[示例二](#示例二可变字体文本阴影占位符)。

#### \[h2\]自动间距

使能自动间距，则会在文本排版时自动调整CJK（中文字符、日文字符、韩文字符）与西文（拉丁字母、西里尔字母、希腊字母）、CJK与数字、CJK与版权符号、版权符号与数字、版权符号与西文之间的间距。例如，在中英文混排场景中，使能自动间距即可在中英文切换的地方自动添加额外间距，提升阅读体验。

关键示例如下：

let myParagraphStyle: text.ParagraphStyle = {
  autoSpace: true
};

#### \[h2\]垂直对齐

垂直对齐用于调整文本在一行中垂直方向的排版位置。开启行高缩放或行内存在不同字号文本混排时使能垂直对齐，可以让文本实现顶部对齐、居中对齐、底部对齐或基线对齐（默认）。关键代码如下：

let myParagraphStyle: text.ParagraphStyle = {
  verticalAlign: text.TextVerticalAlign.CENTER
};

具体使用效果可参见下文[示例三](#示例三垂直对齐)。

#### \[h2\]上下标

使能上下标，能将文本作为上标或下标参与排版。一般用于数学公式、化学式等场景。关键代码如下：

let superScriptStyle: text.TextStyle = {
    badgeType: text.TextBadgeType.TEXT\_SUPERSCRIPT
};

具体使用效果可参见下文[示例四](#示例四上下标文本)。

#### \[h2\]高对比度

高对比度可将深色文字变黑、浅色文字变白。开发者可选择开启或关闭应用的高对比度文字渲染，或遵循系统设置中的高对比度文字配置。

高对比度模式有3种，具体参考[TextHighContrast](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-graphics-text#texthighcontrast20)。

具体使用效果可参见下文[示例五](#示例五高对比度)。

#### \[h2\]行高调整

当前行高调整方式包括两种：设置行高上限/下限和使用行高缩放系数。

**行高调整（方式一）**

从API version 21开始，支持通过设置行高上限和下限调整行高，关键代码如下：

let myTextStyle: text.TextStyle = {
    // 设置行高上限
    lineHeightMaximum: 65,
    // 设置行高下限
    lineHeightMinimum: 65
};

使用效果参考下文[示例六](#示例六行高调整方式一)。

**行高调整（方式二）**

通过设置行高缩放系数调整行高，关键代码如下：

let myTextStyle: text.TextStyle = {
    // 开启行高缩放开关
    heightOnly: true,
    // 设置行高缩放系数
    heightScale: 1.5,
    // 设置行高缩放风格
    lineHeightStyle: text.LineHeightStyle.FONT\_HEIGHT
};

使用效果参考下文[示例七](#示例七行高调整方式二)。

#### \[h2\]行间距调整

从API version 21开始，支持设置行间距改善文本行之间的距离，提高阅读体验，关键代码如下：

let myParagraphStyle: text.ParagraphStyle = {
  // 设置行间距
  lineSpacing: 100,
  // 关闭段落上升部和下降部
  textHeightBehavior: text.TextHeightBehavior.DISABLE\_ALL,
};

具体使用效果可参见下文[示例八](#示例八行间距调整)。

#### \[h2\]省略号样式设置

从API version 22开始，支持设置省略号样式，在文本内容超出显示区域时截断文本。从API version 24开始，支持多行省略模式。

通过[ParagraphStyle](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-graphics-text#paragraphstyle)中的textStyle属性设置省略号模式，可选的省略号模式可见[EllipsisMode](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-graphics-text#ellipsismode)。

需要注意，省略号相关属性需要在ParagraphStyle的textStyle中设置才生效，通过pushStyle设置的省略号属性不会生效。

具体使用效果可参见下文[示例九](#示例九省略号样式)。

#### \[h2\]文字换行方式设置

从API version 22开始，支持在文本排版时设置断行策略，断行策略决定了文本如何在行尾进行换行处理。

通过设置[ParagraphStyle](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-graphics-text#paragraphstyle)中的breakStrategy属性可以控制断行策略，可选的断行策略可见[BreakStrategy](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-graphics-text#breakstrategy)。

具体使用效果可参见下文[示例十](#示例十文字换行方式)。

#### \[h2\]行首标点压缩

从API version 23开始，在文本排版中支持行首标点压缩功能。通过启用行首标点压缩功能，可以将行首标点符号进行挤压处理，提升排版紧凑度。

通过设置[ParagraphStyle](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-graphics-text#paragraphstyle)中的compressHeadPunctuation属性设置是否启用行首标点压缩。

具体使用效果可参见下文[示例十一](#示例十一行首标点压缩)。

#### \[h2\]示例一（装饰线、字体特征）

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

// 创建一个MyRenderNode类，并绘制文本。
class MyRenderNode extends RenderNode {
  async draw(context: DrawContext) {
    let canvas = context.canvas;

    // 初始化装饰线对象
    let decorations: text.Decoration =
      {
        // 装饰线类型，支持上划线、下划线、删除线
        textDecoration: text.TextDecorationType.UNDERLINE,
        // 装饰线颜色
        color: {
          alpha: 255,
          red: 255,
          green: 0,
          blue: 0
        },
        // 装饰线样式，支持波浪，虚线，直线等
        decorationStyle:text.TextDecorationStyle.SOLID,
        // 装饰线的高度
        decorationThicknessScale: 1
      };

    let myTextStyle: text.TextStyle = {
      color: {
        alpha: 255,
        red: 255,
        green: 0,
        blue: 0
      },
      fontSize: 200,
      // 设置装饰线
      decoration: decorations,
      // 开启字体特征
      fontFeatures: \[{name: 'frac', value: 1}\]
    };

    let myParagraphStyle: text.ParagraphStyle = {
      textStyle: myTextStyle,
    };

    let fontCollection = text.FontCollection.getGlobalInstance();
    let paragraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection);

    // 更新文本样式
    paragraphBuilder.pushStyle(myTextStyle);
    // 添加文本
    paragraphBuilder.addText('1/2 1/3 1/4 ');

    // 生成段落
    let paragraph = paragraphBuilder.build();
    // 布局
    paragraph.layoutSync(1250);
    // 绘制文本
    paragraph.paint(canvas, 0, 0);
  }
}

// 创建一个MyRenderNode对象
const textNode = new MyRenderNode();
// 定义newNode的像素格式
textNode.frame = {
  x: 0,
  y: 0,
  width: 400,
  height: 600
};
textNode.pivot = { x: 0.2, y: 0.8 };
textNode.scale = { x: 1, y: 1 };

class MyNodeController extends NodeController {
  private rootNode: FrameNode | null = null;

  makeNode(uiContext: UIContext): FrameNode {
    this.rootNode = new FrameNode(uiContext);
    if (this.rootNode == null) {
      return this.rootNode;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.frame = {
        x: 0,
        y: 0,
        width: 10,
        height: 500
      }
    }
    return this.rootNode;
  }

  addNode(node: RenderNode): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.appendChild(node);
    }
  }

  clearNodes(): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.clearChildren();
    }
  }
}

let myNodeController: MyNodeController = new MyNodeController();

async function performTask() {
  myNodeController.clearNodes();
  myNodeController.addNode(textNode);
}

@Entry
@Component
struct Font08 {
  @State src: Resource = $r('app.media.startIcon');
  build() {
    Column() {
      Row() {
        NodeContainer(myNodeController)
          .height('100%')
          .width('100%')
        Image(this.src)
          .width('0%').height('0%')
          .onComplete(
            () => {
              performTask();
            })
      }
      .width('100%')
    }
  }
}

具体示意效果如下所示：

| 样式设置（装饰线样式、字体特征） | 示意效果 |
| :-- | :-- |
| 不开启装饰线和字体特征 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/36/v3/UPOjLsZpTCm57BQkskUdQQ/zh-cn_image_0000002625188327.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=9641A4AB6C75591DF01C6F571FF0A66201080D23C5C0F542DC9A8694F9960F64) |
| 开启装饰线和字体特征 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/bc/v3/s_CwxILoQkSsRaBnSqVQgA/zh-cn_image_0000002625108471.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=B9EFAEC255C0BFEAB7BFDB1A1A36DA4CD967728414B82A31D5EDB9B0BE4A7045) |

#### \[h2\]示例二（可变字体、文本阴影、占位符）

这里以可变字体、文本阴影、占位符三个特性为例，呈现多样式文本的绘制与显示。

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

// 创建一个MyRenderNode类，并绘制文本。
class MyRenderNode extends RenderNode {
  async draw(context: DrawContext) {
    let canvas = context.canvas;

    let myTextStyle: text.TextStyle = {
      color: {
        alpha: 255,
        red: 255,
        green: 0,
        blue: 0
      },
      fontSize: 120,
      // 可变字体
      fontVariations: \[{axis: 'wght', value: 555}\],
      // 文本阴影
      textShadows: \[{color: { alpha: 0xFF, red: 0xFF, green: 0x00, blue: 0x00 }, point: {x:10,y:10}, blurRadius: 10}\],
    };

    let myParagraphStyle: text.ParagraphStyle = {
      textStyle: myTextStyle,
    };

    let fontCollection = text.FontCollection.getGlobalInstance();
    let paragraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection);

    // 初始化占位符对象
    let myPlaceholderSpan: text.PlaceholderSpan = {
      // 宽度
      width: 300,
      // 高度
      height: 300,
      // 基线对齐策略
      align: text.PlaceholderAlignment.BOTTOM\_OF\_ROW\_BOX,
      // 使用的文本基线类型
      baseline: text.TextBaseline.ALPHABETIC,
      // 相比基线的偏移量。只有对齐策略是OFFSET\_AT\_BASELINE时生效
      baselineOffset: 100
    };
    // 添加占位符
    paragraphBuilder.addPlaceholder(myPlaceholderSpan);

    // 更新文本样式
    paragraphBuilder.pushStyle(myTextStyle);
    // 添加文本
    paragraphBuilder.addText('Hello Test');

    // 生成段落
    let paragraph = paragraphBuilder.build();
    // 布局
    paragraph.layoutSync(1250);
    // 绘制文本
    paragraph.paint(canvas, 0, 0);

    // 获取全部占位符的数组
    let placeholderRects = paragraph.getRectsForPlaceholders();
    // 获取第一个占位符的左边界
    let left = placeholderRects\[0\].rect.left;
    // 获取第一个占位符的上边界
    let top = placeholderRects\[0\].rect.top;
    // 获取第一个占位符的右边界
    let right = placeholderRects\[0\].rect.right;
    // 获取第一个占位符的下边界
    let bottom = placeholderRects\[0\].rect.bottom;
    let pen: drawing.Pen =  new drawing.Pen();
    let penColor : common2D.Color = { alpha: 0xFF, red: 0xFF, green: 0x00, blue: 0x00 };
    pen.setColor(penColor);
    canvas.attachPen(pen);
    // 使用draw方法绘制占位符矩形框
    canvas.drawRect(left,top,right,bottom);
  }
}

// 创建一个MyRenderNode对象
const textNode = new MyRenderNode();
// 定义newNode的像素格式
textNode.frame = {
  x: 0,
  y: 0,
  width: 400,
  height: 600,
};
textNode.pivot = { x: 0.2, y: 0.8 };
textNode.scale = { x: 1, y: 1 };

class MyNodeController extends NodeController {
  private rootNode: FrameNode | null = null;

  makeNode(uiContext: UIContext): FrameNode {
    this.rootNode = new FrameNode(uiContext);
    if (this.rootNode == null) {
      return this.rootNode;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.frame = {
        x: 0,
        y: 0,
        width: 10,
        height: 500
      };
    }
    return this.rootNode;
  }

  addNode(node: RenderNode): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.appendChild(node);
    }
  }

  clearNodes(): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.clearChildren();
    }
  }
}

let myNodeController: MyNodeController = new MyNodeController();

async function performTask() {
  myNodeController.clearNodes();
  myNodeController.addNode(textNode);
}

@Entry
@Component
struct Font08 {
  @State src: Resource = $r('app.media.startIcon');
  build() {
    Column() {
      Row() {
        NodeContainer(myNodeController)
          .height('100%')
          .width('100%')
        Image(this.src)
          .width('0%').height('0%')
          .onComplete(
            () => {
              performTask();
            })
      }
      .width('100%')
    }
  }
}

具体示意效果如下所示：

| 样式设置（可变字体、文本阴影、占位符） | 示意效果 |
| :-- | :-- |
| 不开启可变字体和文本阴影，不使用占位符 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/db/v3/dp9UB47WT-mPXbcdAMQhpg/zh-cn_image_0000002594668954.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=D61D3C8A4A4E8C85B9308B878A439A46C627A4884B0CDBCB9EDC04B792C7B343) |
| 开启可变字体和文本阴影，使用占位符 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/35/v3/c9GZA5PlR0mUqVjqTfvQDA/zh-cn_image_0000002594828882.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=F54594D303657BD8A9565AFBB713C77FA2CAFB4DC4172876E2CE586046DDCE73) |

#### \[h2\]示例三（垂直对齐）

这里以垂直对齐-居中对齐特性为例，呈现文本垂直方向排版的特性。

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

// 创建一个MyRenderNode类，并绘制文本。
class MyRenderNode extends RenderNode {
  async draw(context: DrawContext) {
    let canvas = context.canvas;

    let myTextStyle: text.TextStyle = {
      color: {
        alpha: 255,
        red: 255,
        green: 0,
        blue: 0
      },
      fontSize: 30,
      // 开启行高缩放
      heightOnly: true,
      // 行高缩放系数为字号的2倍
      heightScale: 2
    };

    let myParagraphStyle: text.ParagraphStyle = {
      textStyle: myTextStyle,
      // 设置垂直对齐-居中对齐模式
      verticalAlign: text.TextVerticalAlign.CENTER,
    };

    let fontCollection = text.FontCollection.getGlobalInstance();
    let paragraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection);

    // 设置待排版文本要应用的样式
    paragraphBuilder.pushStyle(myTextStyle);
    // 添加文本
    paragraphBuilder.addText('VerticalAlignment-center');

    // 生成段落
    let paragraph = paragraphBuilder.build();
    // 布局
    paragraph.layoutSync(1000);
    // 绘制文本
    paragraph.paint(canvas, 0, 0);
  }
}

// 创建一个MyRenderNode对象
const textNode = new MyRenderNode();
// 定义newNode的像素格式
textNode.frame = {
  x: 0,
  y: 0,
  width: 400,
  height: 600
};
textNode.pivot = { x: 0.2, y: 0.8 };
textNode.scale = { x: 1, y: 1 };

class MyNodeController extends NodeController {
  private rootNode: FrameNode | null = null;

  makeNode(uiContext: UIContext): FrameNode {
    this.rootNode = new FrameNode(uiContext);
    if (this.rootNode == null) {
      return this.rootNode;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.frame = {
        x: 0,
        y: 0,
        width: 10,
        height: 500
      }
      renderNode.pivot = { x: 50, y: 50 };
    }
    return this.rootNode;
  }

  addNode(node: RenderNode): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.appendChild(node);
    }
  }

  clearNodes(): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.clearChildren();
    }
  }
}

let myNodeController: MyNodeController = new MyNodeController();

async function performTask() {
  myNodeController.clearNodes();
  myNodeController.addNode(textNode);
}

@Entry
@Component
struct Font08 {
  @State src: Resource = $r('app.media.startIcon');
  build() {
    Column() {
      Row() {
        NodeContainer(myNodeController)
          .height('100%')
          .width('100%')
        Text('Test for vertical alignment')
          .onAppear(() => {
            performTask();
          })
      }
      .width('100%')
    }
  }
}

具体示意效果如下所示：

| 样式设置（垂直对齐） | 示意效果（黑框仅为展示文本绘制区域，实际不绘制） |
| :-- | :-- |
| 基线对齐（默认） | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/a7/v3/Iw1R-co4RRy3FdSAtI1mag/zh-cn_image_0000002625188329.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=DE89435675D81333C015E888694718AA2DA043F68EFC75DAFDB13113D4FA427C) |
| 顶部对齐 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/c4/v3/cRq-LI0_TYC43ejFbKzrYA/zh-cn_image_0000002625108473.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=3D9F986F8491C3DAE93A1B533E84B1E2B8466ABF5E580AC61FB8EB14A862760C) |
| 居中对齐 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/17/v3/8Grwt_HYSAirrRuWLgpznw/zh-cn_image_0000002594668956.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=88AAE4952CE50E35BF2E480217742A323BD44D6C37023666657A922839DC6BD6) |
| 底部对齐 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/c8/v3/DqUaR1tTSkGsgw8mmY628w/zh-cn_image_0000002594828884.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=6A2424BBD7A13D63B4FB35617B44EB2067C8E21BEA97CE09D511D635151B0C7B) |

#### \[h2\]示例四（上下标文本）

这里以下标样式为例，呈现上下标文本排版特性。

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

// 创建一个MyRenderNode类，并绘制文本。
class MyRenderNode extends RenderNode {
  async draw(context: DrawContext) {
    let canvas = context.canvas;

    let myTextStyle: text.TextStyle = {
      color: {
        alpha: 255,
        red: 255,
        green: 0,
        blue: 0
      },
      fontSize: 30,
    };

    let subScriptStyle: text.TextStyle = {
      color: {
        alpha: 255,
        red: 255,
        green: 0,
        blue: 0
      },
      fontSize: 30,
      // 设置下标样式
      badgeType: text.TextBadgeType.TEXT\_SUBSCRIPT
    };

    let myParagraphStyle: text.ParagraphStyle = {
      textStyle: myTextStyle,
    };

    let fontCollection = text.FontCollection.getGlobalInstance();
    let paragraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection);

    // 设置待排版文本要应用的样式
    paragraphBuilder.pushStyle(myTextStyle);
    // 添加文本
    paragraphBuilder.addText('The chemical formula for water: H');
    paragraphBuilder.pushStyle(subScriptStyle);
    paragraphBuilder.addText('2');
    paragraphBuilder.pushStyle(myTextStyle);
    paragraphBuilder.addText('o');

    // 生成段落
    let paragraph = paragraphBuilder.build();
    // 布局
    paragraph.layoutSync(1000);
    // 绘制文本
    paragraph.paint(canvas, 0, 0);
  }
}

// 创建一个MyRenderNode对象
const textNode = new MyRenderNode();
// 定义newNode的像素格式
textNode.frame = {
  x: 0,
  y: 0,
  width: 400,
  height: 600
};
textNode.pivot = { x: 0.2, y: 0.8 };
textNode.scale = { x: 1, y: 1 };

class MyNodeController extends NodeController {
  private rootNode: FrameNode | null = null;

  makeNode(uiContext: UIContext): FrameNode {
    this.rootNode = new FrameNode(uiContext);
    if (this.rootNode == null) {
      return this.rootNode;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.frame = {
        x: 0,
        y: 0,
        width: 10,
        height: 500
      }
      renderNode.pivot = { x: 50, y: 50 };
    }
    return this.rootNode;
  }

  addNode(node: RenderNode): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.appendChild(node);
    }
  }

  clearNodes(): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.clearChildren();
    }
  }
}

let myNodeController: MyNodeController = new MyNodeController();

async function performTask() {
  myNodeController.clearNodes();
  myNodeController.addNode(textNode);
}

@Entry
@Component
struct Font08 {
  @State src: Resource = $r('app.media.startIcon');
  build() {
    Column() {
      Row() {
        NodeContainer(myNodeController)
          .height('100%')
          .width('100%')
        Text('Test for superscript and subscript')
          .onAppear(() => {
            performTask();
          })
      }
    }
    .width('100%')
  }
}

具体示意效果如下所示：

| 样式设置（上下标） | 示意效果 |
| :-- | :-- |
| 上标文本 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/59/v3/lRx2cageRNGb4sdr0FX7Cg/zh-cn_image_0000002625188331.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=FF59BEF909087031EF74626E926ADD4E4AB63446F771B975F6DD63F897333FF0) |
| 下标文本 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/3e/v3/rJz6_RjFTumZEUGJyYqCOw/zh-cn_image_0000002625108475.jpg?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=8BB1DA4093B78CEAADDB7229B77E019446EA34A64595FE528313B837A5096117) |

#### \[h2\]示例五（高对比度）

这里以高对比度为例，呈现高对比度文字的绘制与显示。

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

// 创建一个MyRenderNode类，并绘制文本。
class MyRenderNode extends RenderNode {
  async draw(context: DrawContext) {
    let canvas = context.canvas;

    // 开启APP的文字渲染高对比度配置
    text.setTextHighContrast(text.TextHighContrast.TEXT\_APP\_ENABLE\_HIGH\_CONTRAST);

    let myTextStyle: text.TextStyle = {
      color: {
        alpha: 255,
        red: 111,
        green: 255,
        blue: 255
      },
      fontSize: 100,
    };

    let myParagraphStyle: text.ParagraphStyle = {
      textStyle: myTextStyle,
    };

    let fontCollection = text.FontCollection.getGlobalInstance();
    let paragraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection);

    // 更新文本样式
    paragraphBuilder.pushStyle(myTextStyle);
    // 添加文本
    paragraphBuilder.addText('Hello World');

    // 生成段落
    let paragraph = paragraphBuilder.build();
    // 布局
    paragraph.layoutSync(1250);
    // 绘制文本
    paragraph.paint(canvas, 10, 800);
  }
}

// 创建一个MyRenderNode对象
const textNode = new MyRenderNode();
// 定义newNode的像素格式
textNode.frame = {
  x: 0,
  y: 0,
  width: 400,
  height: 600
};
textNode.pivot = { x: 0.2, y: 0.8 };
textNode.scale = { x: 1, y: 1 };

class MyNodeController extends NodeController {
  private rootNode: FrameNode | null = null;

  makeNode(uiContext: UIContext): FrameNode {
    this.rootNode = new FrameNode(uiContext);
    if (this.rootNode == null) {
      return this.rootNode;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.frame = {
        x: 0,
        y: 0,
        width: 10,
        height: 500
      };
      renderNode.pivot = { x: 0.2, y: 0.8 };
    }
    return this.rootNode;
  }

  addNode(node: RenderNode): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.appendChild(node);
    }
  }

  clearNodes(): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.clearChildren();
    }
  }
}

let myNodeController: MyNodeController = new MyNodeController();

async function performTask() {
  myNodeController.clearNodes();
  myNodeController.addNode(textNode);
}

@Entry
@Component
struct Font08 {
  build() {
    Column() {
      Row() {
        NodeContainer(myNodeController)
          .height('100%')
          .width('100%')
        Text('Test high contrast')
          .onAppear(() => {
            performTask();
          })
      }
      .width('100%')
    }
  }
}

具体示意效果如下所示：

| 高对比度设置 | 示意效果 |
| :-- | :-- |
| 不开启高对比度 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/5c/v3/u4_GEEWzTVOrPuTgGAu2yw/zh-cn_image_0000002594668958.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=8A1EEA02106332BC38EEE6224F669F4E5FE74436D5393D0AE56D46D6F6A417C0) |
| 开启高对比度 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/8c/v3/uX6jnz2kRYWGOTqo2itigQ/zh-cn_image_0000002594828886.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=B4F0C17036FE342248B7FF52F630AE2E297D5AAD9265B26074BE8F59FC08C93E) |

#### \[h2\]示例六（行高调整方式一）

这里以行高上限与行高下限设置相同值为例，呈现固定行高时的绘制表现。

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

// 创建一个MyRenderNode类，并绘制文本。
class MyRenderNode extends RenderNode {
  async draw(context: DrawContext) {
    let canvas = context.canvas;

    let myTextStyle: text.TextStyle = {
      color: {
        alpha: 255,
        red: 255,
        green: 0,
        blue: 0
      },
      fontSize: 50,
      // 设置行高上限
      lineHeightMaximum: 65,
      // 设置行高下限
      lineHeightMinimum: 65,
    };

    let myParagraphStyle: text.ParagraphStyle = {
      textStyle: myTextStyle,
    };

    let fontCollection = text.FontCollection.getGlobalInstance();
    let paragraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection);

    // 设置待排版文本要应用的样式
    paragraphBuilder.pushStyle(myTextStyle);
    // 添加文本
    paragraphBuilder.addText('Hello World!');

    // 生成段落
    let paragraph = paragraphBuilder.build();
    // 布局
    paragraph.layoutSync(1000);
    // 绘制文本
    paragraph.paint(canvas, 0, 0);
  }
}

// 创建一个MyRenderNode对象
const textNode = new MyRenderNode()
// 定义newNode的像素格式
textNode.frame = {
  x: 0,
  y: 0,
  width: 400,
  height: 600
}
textNode.pivot = { x: 0.2, y: 0.8 };
textNode.scale = { x: 1, y: 1 };

class MyNodeController extends NodeController {
  private rootNode: FrameNode | null = null;

  makeNode(uiContext: UIContext): FrameNode {
    this.rootNode = new FrameNode(uiContext)
    if (this.rootNode == null) {
      return this.rootNode;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.frame = {
        x: 0,
        y: 0,
        width: 10,
        height: 500
      }
      renderNode.pivot = { x: 50, y: 50 };
    }
    return this.rootNode;
  }

  addNode(node: RenderNode): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.appendChild(node);
    }
  }

  clearNodes(): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode()
    if (renderNode != null) {
      renderNode.clearChildren();
    }
  }
}

let myNodeController: MyNodeController = new MyNodeController();

async function performTask() {
  myNodeController.clearNodes();
  myNodeController.addNode(textNode);
}

@Entry
@Component
struct Font08 {
  @State src: Resource = $r('app.media.startIcon')
  build() {
    Column() {
      Row() {
        NodeContainer(myNodeController)
          .height('100%')
          .width('100%')
        Text('Test for line height limit')
          .onAppear(() => {
            performTask();
          })
      }
    }
    .width('100%')
  }
}

具体效果如下所示：

| 行高上限值 | 行高下限值 | 示意效果（黑框仅为展示文本绘制区域，实际不绘制） |
| :-- | :-- | :-- |
| 65 | 65 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/0b/v3/k-3i5c8vSriakdkSnYjL_A/zh-cn_image_0000002625188333.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=6065840D0D271A68C66A14F1BDD4E4075529830B2FA7D1706BF2C9F18768FBE5) |
| 200 | 200 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/bf/v3/3EbsOmCUQDSOZhRsEl1Rag/zh-cn_image_0000002625108477.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=5EF8B78C6940CD0599AF82E557C84BB1C2251D3B2E43960BC335CB398B6787A5) |

#### \[h2\]示例七（行高调整方式二）

这里以行高缩放且行高缩放样式FontHeight为例，呈现行高调整后文字的绘制与显示。

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

// 创建一个MyRenderNode类，并绘制文本。
class MyRenderNode extends RenderNode {
  async draw(context: DrawContext) {
    let canvas = context.canvas;

    let myTextStyle: text.TextStyle = {
      color: {
        alpha: 255,
        red: 255,
        green: 0,
        blue: 0
      },
      fontSize: 50,
      // 开启行高缩放开关
      heightOnly: true,
      // 设置行高缩放系数
      heightScale: 1.5,
      // 设置行高缩放风格
      lineHeightStyle: text.LineHeightStyle.FONT\_HEIGHT,
    };

    let myParagraphStyle: text.ParagraphStyle = {
      textStyle: myTextStyle,
    };

    let fontCollection = text.FontCollection.getGlobalInstance();
    let paragraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection);

    // 设置待排版文本要应用的样式
    paragraphBuilder.pushStyle(myTextStyle);
    // 添加文本
    paragraphBuilder.addText('Hello World!');

    // 生成段落
    let paragraph = paragraphBuilder.build();
    // 布局
    paragraph.layoutSync(1000);
    // 绘制文本
    paragraph.paint(canvas, 0, 0);
  }
}

// 创建一个MyRenderNode对象
const textNode = new MyRenderNode();
// 定义newNode的像素格式
textNode.frame = {
  x: 0,
  y: 0,
  width: 400,
  height: 600
}
textNode.pivot = { x: 0.2, y: 0.8 };
textNode.scale = { x: 1, y: 1 };

class MyNodeController extends NodeController {
  private rootNode: FrameNode | null = null;

  makeNode(uiContext: UIContext): FrameNode {
    this.rootNode = new FrameNode(uiContext)
    if (this.rootNode == null) {
      return this.rootNode;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.frame = {
        x: 0,
        y: 0,
        width: 10,
        height: 500
      };
      renderNode.pivot = { x: 50, y: 50 };
    }
    return this.rootNode;
  }

  addNode(node: RenderNode): void {
    if (this.rootNode == null) {
      return
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.appendChild(node);
    }
  }

  clearNodes(): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode()
    if (renderNode != null) {
      renderNode.clearChildren();
    }
  }
}

let myNodeController: MyNodeController = new MyNodeController();

async function performTask() {
  myNodeController.clearNodes();
  myNodeController.addNode(textNode);
}

@Entry
@Component
struct Font08 {
  @State src: Resource = $r('app.media.startIcon')
  build() {
    Column() {
      Row() {
        NodeContainer(myNodeController)
          .height('100%')
          .width('100%')
        Text('Test for line height limit')
          .onAppear(() => {
            performTask();
          })
      }
    }
    .width('100%')
  }
}

具体效果如下所示：

| 行高缩放样式 | 示意效果（黑框仅为展示文本绘制区域，实际不绘制） |
| :-- | :-- |
| FontSize | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/3b/v3/8mbwOm_FQTiVbUpXBZHouw/zh-cn_image_0000002594668960.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=20552D0310DC088B166FEC316EF8E1E316A6D37AED6BED297EBC49D0EF775FB4) |
| FontHeight | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/6/v3/P8qEWu6yTbelD4AS6oS1Lg/zh-cn_image_0000002594828888.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=BD0A9974E9D0B033D9AA16B4CF6F40CA8B7E269148CC1E218FCBC8B8B8D9744D) |

#### \[h2\]示例八（行间距调整）

这里以关闭段落上升部下降部并设置行间距为例，呈现行间距增加后的文本绘制与显示。

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

// 创建一个MyRenderNode类，并绘制文本。
class MyRenderNode extends RenderNode {
  async draw(context: DrawContext) {
    let canvas = context.canvas;

    let myTextStyle: text.TextStyle = {
      color: {
        alpha: 255,
        red: 255,
        green: 0,
        blue: 0
      },
      fontSize: 50,
    };

    let myParagraphStyle: text.ParagraphStyle = {
      textStyle: myTextStyle,
      // 设置行间距
      lineSpacing: 100,
      // 关闭段落上升部和下降部
      textHeightBehavior: text.TextHeightBehavior.DISABLE\_ALL,
    };

    let fontCollection = text.FontCollection.getGlobalInstance();
    let paragraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection);

    // 设置待排版文本要应用的样式
    paragraphBuilder.pushStyle(myTextStyle);
    // 添加文本
    paragraphBuilder.addText('Hello World!');

    // 生成段落
    let paragraph = paragraphBuilder.build();
    // 布局
    paragraph.layoutSync(200);
    // 绘制文本
    paragraph.paint(canvas, 0, 0);
  }
}

// 创建一个MyRenderNode对象
const textNode = new MyRenderNode();
// 定义newNode的像素格式
textNode.frame = {
  x: 0,
  y: 0,
  width: 400,
  height: 600
}
textNode.pivot = { x: 0.2, y: 0.8 };
textNode.scale = { x: 1, y: 1 };

class MyNodeController extends NodeController {
  private rootNode: FrameNode | null = null;

  makeNode(uiContext: UIContext): FrameNode {
    this.rootNode = new FrameNode(uiContext);
    if (this.rootNode == null) {
      return this.rootNode
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.frame = {
        x: 0,
        y: 0,
        width: 10,
        height: 500
      }
      renderNode.pivot = { x: 50, y: 50 };
    }
    return this.rootNode;
  }

  addNode(node: RenderNode): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.appendChild(node);
    }
  }

  clearNodes(): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.clearChildren();
    }
  }
}

let myNodeController: MyNodeController = new MyNodeController();

async function performTask() {
  myNodeController.clearNodes();
  myNodeController.addNode(textNode);
}

@Entry
@Component
struct Font08 {
  @State src: Resource = $r('app.media.startIcon')
  build() {
    Column() {
      Row() {
        NodeContainer(myNodeController)
          .height('100%')
          .width('100%')
        Text('Test for lineSpacing and height behavior')
          .onAppear(() => {
            performTask();
          })
      }
    }
    .width('100%')
  }
}

具体效果如下所示：

| 上升部下降部开关 | 示意效果（黑框仅为展示文本绘制区域，实际不绘制） |
| :-- | :-- |
| DISABLE\_ALL | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/8e/v3/M0ihnEHhQz6cJRkk-gzQag/zh-cn_image_0000002625188335.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=6C3FDB253B420688C45C32C7AA1997ABAC784D9BEFC355CA2A4207A08BF772BC) |
| ALL | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/62/v3/ISQXFRntTAWILATAht8MTQ/zh-cn_image_0000002625108479.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=9C1BFA97553B1E715E276120AE77CFCDED504B21DF80D2145B7657A8A31F1E01) |

#### \[h2\]示例九（省略号样式）

以下示例展示了开启尾部省略号模式的文本截断效果。

// 设置文本样式，包含省略号字符串和省略号模式
let myTextStyle: text.TextStyle = {
  color: {
    alpha: 255,
    red: 0,
    green: 0,
    blue: 0
  },
  fontSize: 40,
  // 设置省略号字符串
  ellipsis: '...',
  // 设置省略号模式为尾部省略
  ellipsisMode: text.EllipsisMode.END
};
// 设置段落样式，包含最大行数
let myParagraphStyle: text.ParagraphStyle = {
  textStyle: myTextStyle,
  // 设置最大显示行数为2
  maxLines: 2
};

具体效果如下所示：

| 省略号模式 | 示意效果 |
| :-- | :-- |
| 不开启省略号 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/91/v3/w1kjRBdgSjOhWFLeNXDxhw/zh-cn_image_0000002594668962.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=89CC293CF6A52795CDF04205C07A38AB10BE31E488A9A7F0447A5F272DC8FC02) |
| 开启头部省略号 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/59/v3/f8x03EfgTmSlq8oIwsNEAw/zh-cn_image_0000002594828890.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=AABCA546A9BDE5C7D9EF122A73598D602A5136C92124C1E41980059CEEB677CF) |
| 开启中部省略号 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/81/v3/5vLMHeB9RAGgyNos1gpkew/zh-cn_image_0000002625188337.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=27A47271C21EE2542B3E9E19BEF590F3F2B8EEA2EECFDC057DA1F678B4D4FF3C) |
| 开启尾部省略号 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/e9/v3/2Jfl3bfOSq-wzyU86CV5jg/zh-cn_image_0000002625108481.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=B492B50A33250915953FE61B47B92C0F238AA2B2E275D521818E08CE6A24A4F6) |
| 开启多行头部省略号 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/1c/v3/6iDZNW6lTiCNTFqbZ_LLeQ/zh-cn_image_0000002594668964.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=3B5C686F780080563F15AB7FBD7EE35387075EB25C899CFBED1585FD91A24847) |
| 开启多行中部省略号 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/ac/v3/_QTiojfxTR6AXh8GdymXaQ/zh-cn_image_0000002594828892.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=3A75618454427F864399905AF422C50FC5F5C762DD99BA248F89160891B0E30D) |

#### \[h2\]示例十（文字换行方式）

以下示例展示了BALANCED断行策略对文本排版的影响。

// 设置断行策略为均衡策略（BALANCED）
let myParagraphStyle: text.ParagraphStyle = {
  textStyle: myTextStyle,
  // 设置断行策略为均衡策略，各行宽度尽量均衡
  breakStrategy: text.BreakStrategy.BALANCED
};

具体效果如下所示：

| 断行策略 | 示意效果 |
| :-- | :-- |
| GREEDY | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/1a/v3/LenbwWBcTZeoJAfZvNHbHg/zh-cn_image_0000002625188339.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=B6F8D28A065374C35B234A7DCD07012DA0560E5F8A4650852FF37E0A91C218F5) |
| BALANCED | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/98/v3/1CjTJDRNT5yZhRXcXu44_Q/zh-cn_image_0000002625108483.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=A79E611376D236C95022234184BEF5FFDDD07ECDE82EB8DD567808738C77C831) |
| HIGH\_QUALITY | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/fd/v3/5T7DiqG1RNOgMzBmNgXUtQ/zh-cn_image_0000002594668966.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=FE057B8A4D7FB855F1C77273B048282BA3E68E8ADF9D40AEEE981C1B024CD2F1) |

#### \[h2\]示例十一（行首标点压缩）

以下示例展示了开启行首标点压缩的排版对比效果。

// 开启行首标点压缩
let myParagraphStyle: text.ParagraphStyle = {
  textStyle: myTextStyle,
  compressHeadPunctuation: true
};

具体效果如下所示：

| 标点压缩设置 | 示意效果 |
| :-- | :-- |
| 未开启标点压缩 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/ba/v3/l-0VrTO5QImMGODJ6hNnnA/zh-cn_image_0000002594828894.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=4A54B23301B2B7C9E411CD8AF17F3D79FF078B3225C357C2A457F8984A0B005A) |
| 开启标点压缩 | ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/c3/v3/RFQwc15-R7GwSvzepIypAQ/zh-cn_image_0000002625188341.png?HW-CC-KV=V1&HW-CC-Date=20260612T073537Z&HW-CC-Expire=86400&HW-CC-Sign=4B6745FDE425B1989AB1B27272DBF3B2B636D16BAE924DAE7D732ABC040A4DB1) |