1# 复杂文本绘制与显示(ArkTS) 2 3在进行文本绘制时,可以通过选择合适的字体、大小和颜色完成简单文本的绘制与显示;此外,还支持通过设置其他丰富的样式、语言、段落等进行复杂文本的绘制。 4 5复杂文本绘制主要包含以下几个场景: 6 7- 多语言文本绘制与显示 8 9- 多行文本绘制与显示 10 11- 多类型文本绘制与显示 12 13 14## 多语言文本绘制与显示 15 16多语言支持是全球化应用的基础。多语言文本绘制需要支持不同语言的字符集及其独特的显示需求,例如右到左语言(如阿拉伯语)或竖排文本(如中文)。开发者需要理解不同语言的渲染特性,确保文本的正确显示。 17 18 19在多语言文本使用的场景下,主要通过指定[TextStyle](../reference/apis-arkgraphics2d/js-apis-graphics-text.md#textstyle)文本样式中的**locale**字段来实现,可直接通过locale字段的值优先匹配对应字体,跳过遍历列表匹配字体的过程,从而降低匹配时间和内存使用。 20 21 22### 开发步骤 23 241. 通过context获取到Canvas画布对象。 25 26 ```ts 27 let canvas = context.canvas; 28 ``` 29 302. 初始化文本样式。 31 32 ```ts 33 let myTextStyle: text.TextStyle = { 34 color: { 35 alpha: 255, 36 red: 255, 37 green: 0, 38 blue: 0 39 }, 40 fontSize: 50, 41 // 设置语言偏好为简体中文 42 locale: "zh-Hans" 43 }; 44 ``` 45 463. 初始化段落样式。 47 48 ```ts 49 let myParagraphStyle: text.ParagraphStyle = { 50 textStyle: myTextStyle, 51 }; 52 ``` 53 544. 初始化段落对象,并添加文本。 55 56 ```ts 57 let fontCollection = text.FontCollection.getGlobalInstance(); 58 let ParagraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection); 59 // 更新文本样式 60 ParagraphGraphBuilder.pushStyle(myTextStyle); 61 // 添加文本 62 ParagraphGraphBuilder.addText("你好,世界"); 63 ``` 64 655. 排版段落并进行文本绘制。 66 67 ```ts 68 // 生成段落 69 let paragraph = ParagraphGraphBuilder.build(); 70 // 布局 71 paragraph.layoutSync(1250); 72 // 绘制文本 73 paragraph.paint(canvas, 10, 0); 74 ``` 75 76 77### 完整示例 78 79此示例中,要绘制的文本为简体中文,将语言偏好设置为简体中文,在匹配文字字体时,会优先匹配简体,从而提高绘制的效率。 80 81```ts 82import { NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI' 83import { UIContext } from '@kit.ArkUI' 84import { drawing } from '@kit.ArkGraphics2D' 85import { text } from '@kit.ArkGraphics2D' 86import { image } from '@kit.ImageKit' 87import { common2D } from '@kit.ArkGraphics2D' 88 89// 创建一个MyRenderNode类,并绘制文本。 90class MyRenderNode extends RenderNode { 91 async draw(context: DrawContext) { 92 // 绘制代码逻辑写在这里 93 let canvas = context.canvas; 94 95 let myTextStyle: text.TextStyle = { 96 color: { 97 alpha: 255, 98 red: 255, 99 green: 0, 100 blue: 0 101 }, 102 fontSize: 50, 103 // 设置语言偏好为简体中文 104 locale: "zh-Hans" 105 }; 106 107 let myParagraphStyle: text.ParagraphStyle = { 108 textStyle: myTextStyle, 109 }; 110 let fontCollection = text.FontCollection.getGlobalInstance(); 111 let ParagraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection); 112 // 更新文本样式 113 ParagraphGraphBuilder.pushStyle(myTextStyle); 114 // 添加文本 115 ParagraphGraphBuilder.addText("你好,世界"); 116 // 生成段落 117 let paragraph = ParagraphGraphBuilder.build(); 118 // 布局 119 paragraph.layoutSync(1250); 120 // 绘制文本 121 paragraph.paint(canvas, 10, 0); 122 } 123} 124 125// 创建一个MyRenderNode对象 126const textNode = new MyRenderNode() 127// 定义newNode的像素格式 128textNode.frame = { 129 x: 0, 130 y: 100, 131 width: 1250, 132 height: 800 133} 134textNode.pivot = { x: 0.2, y: 0.8 } 135textNode.scale = { x: 1, y: 1 } 136 137class MyNodeController extends NodeController { 138 private rootNode: FrameNode | null = null; 139 140 makeNode(uiContext: UIContext): FrameNode { 141 this.rootNode = new FrameNode(uiContext) 142 if (this.rootNode == null) { 143 return this.rootNode 144 } 145 const renderNode = this.rootNode.getRenderNode() 146 if (renderNode != null) { 147 renderNode.frame = { 148 x: 0, 149 y: 0, 150 width: 10, 151 height: 500 152 } 153 renderNode.pivot = { x: 50, y: 50 } 154 } 155 return this.rootNode 156 } 157 158 addNode(node: RenderNode): void { 159 if (this.rootNode == null) { 160 return 161 } 162 const renderNode = this.rootNode.getRenderNode() 163 if (renderNode != null) { 164 renderNode.appendChild(node) 165 } 166 } 167 168 clearNodes(): void { 169 if (this.rootNode == null) { 170 return 171 } 172 const renderNode = this.rootNode.getRenderNode() 173 if (renderNode != null) { 174 renderNode.clearChildren() 175 } 176 } 177} 178 179let myNodeController: MyNodeController = new MyNodeController() 180 181async function performTask() { 182 myNodeController.clearNodes() 183 myNodeController.addNode(textNode) 184} 185 186@Entry 187@Component 188struct Font08 { 189 @State src: Resource = $r('app.media.startIcon') 190 build() { 191 Column() { 192 Row() { 193 NodeContainer(myNodeController) 194 .height('100%') 195 .width('100%') 196 Image(this.src) 197 .width('0%').height('0%') 198 .onComplete( 199 () => { 200 performTask(); 201 }) 202 } 203 .width('100%') 204 } 205 } 206} 207``` 208 209 210### 效果展示 211 212 213 214 215## 多行文本绘制与显示 216 217多行文本相对于单行文本比较复杂,一般针对多行文本,需要进行文本排版、断词策略设置、文本对齐方式、最大行数限制等,主要通过设置段落样式实现。 218 219 220### 实现说明 221 222**段落样式**([ParagraphStyle](../reference/apis-arkgraphics2d/js-apis-graphics-text.md#paragraphstyle))是对多行文本中每段内容的样式设置,包括断词策略、文本对齐方式、最大行数限制等。开发者可以通过对不同段落进行样式化,以提高文本的可读性和美观性。 223 224 225### 开发步骤 226 2271. 通过context获取到Canvas画布对象。 228 229 ```ts 230 // 绘制代码逻辑写在这里 231 let canvas = context.canvas; 232 ``` 233 2342. 初始化文本样式。 235 236 ```ts 237 let myTextStyle: text.TextStyle = { 238 color: { 239 alpha: 255, 240 red: 255, 241 green: 0, 242 blue: 0 243 }, 244 fontSize: 50, 245 }; 246 ``` 247 2483. 初始化段落样式。 249 250 ```ts 251 let myParagraphStyle: text.ParagraphStyle = { 252 textStyle: myTextStyle, 253 // 本文对齐方式 254 align: text.TextAlign.LEFT, 255 // 最大行数 256 maxLines: 3, 257 // 断词策略 258 wordBreak: text.WordBreak.BREAK_WORD 259 }; 260 ``` 261 2624. 初始化段落对象,并添加占位符和文本。 263 264 ```ts 265 let fontCollection = text.FontCollection.getGlobalInstance(); 266 let ParagraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection); 267 // 更新文本样式 268 ParagraphGraphBuilder.pushStyle(myTextStyle); 269 // 添加文本 270 ParagraphGraphBuilder.addText("Hello World Hello World Hello World Hello World Hello World Hello World " + 271 "Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World " + 272 "Hello World Hello World Hello World Hello World Hello World "); 273 ``` 274 2755. 排版段落并进行文本绘制。 276 277 ```ts 278 // 生成段落 279 let paragraph = ParagraphGraphBuilder.build(); 280 // 布局 281 paragraph.layoutSync(1250); 282 // 绘制文本 283 paragraph.paint(canvas, 10, 0); 284 ``` 285 286 287### 完整示例 288 289```ts 290import { NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI' 291import { UIContext } from '@kit.ArkUI' 292import { drawing } from '@kit.ArkGraphics2D' 293import { text } from '@kit.ArkGraphics2D' 294import { image } from '@kit.ImageKit' 295import { common2D } from '@kit.ArkGraphics2D' 296 297// 创建一个MyRenderNode类,并绘制文本。 298class MyRenderNode extends RenderNode { 299 async draw(context: DrawContext) { 300 // 绘制代码逻辑写在这里 301 let canvas = context.canvas; 302 303 let myTextStyle: text.TextStyle = { 304 color: { 305 alpha: 255, 306 red: 255, 307 green: 0, 308 blue: 0 309 }, 310 fontSize: 50, 311 }; 312 313 let myParagraphStyle: text.ParagraphStyle = { 314 textStyle: myTextStyle, 315 // 本文对齐方式 316 align: text.TextAlign.LEFT, 317 // 最大行数 318 maxLines: 3, 319 // 断词策略 320 wordBreak: text.WordBreak.BREAK_WORD 321 }; 322 let fontCollection = text.FontCollection.getGlobalInstance(); 323 let ParagraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection); 324 // 更新文本样式 325 ParagraphGraphBuilder.pushStyle(myTextStyle); 326 // 添加文本 327 ParagraphGraphBuilder.addText("Hello World Hello World Hello World Hello World Hello World Hello World " + 328 "Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World " + 329 "Hello World Hello World Hello World Hello World Hello World "); 330 // 生成段落 331 let paragraph = ParagraphGraphBuilder.build(); 332 // 布局 333 paragraph.layoutSync(1250); 334 // 绘制文本 335 paragraph.paint(canvas, 10, 0); 336 } 337} 338 339// 创建一个MyRenderNode对象 340const textNode = new MyRenderNode() 341// 定义newNode的像素格式 342textNode.frame = { 343 x: 0, 344 y: 100, 345 width: 1250, 346 height: 800 347} 348textNode.pivot = { x: 0.2, y: 0.8 } 349textNode.scale = { x: 1, y: 1 } 350 351class MyNodeController extends NodeController { 352 private rootNode: FrameNode | null = null; 353 354 makeNode(uiContext: UIContext): FrameNode { 355 this.rootNode = new FrameNode(uiContext) 356 if (this.rootNode == null) { 357 return this.rootNode 358 } 359 const renderNode = this.rootNode.getRenderNode() 360 if (renderNode != null) { 361 renderNode.frame = { 362 x: 0, 363 y: 0, 364 width: 10, 365 height: 500 366 } 367 renderNode.pivot = { x: 50, y: 50 } 368 } 369 return this.rootNode 370 } 371 372 addNode(node: RenderNode): void { 373 if (this.rootNode == null) { 374 return 375 } 376 const renderNode = this.rootNode.getRenderNode() 377 if (renderNode != null) { 378 renderNode.appendChild(node) 379 } 380 } 381 382 clearNodes(): void { 383 if (this.rootNode == null) { 384 return 385 } 386 const renderNode = this.rootNode.getRenderNode() 387 if (renderNode != null) { 388 renderNode.clearChildren() 389 } 390 } 391} 392 393let myNodeController: MyNodeController = new MyNodeController() 394 395async function performTask() { 396 myNodeController.clearNodes() 397 myNodeController.addNode(textNode) 398} 399 400@Entry 401@Component 402struct Font08 { 403 @State src: Resource = $r('app.media.startIcon') 404 build() { 405 Column() { 406 Row() { 407 NodeContainer(myNodeController) 408 .height('100%') 409 .width('100%') 410 Image(this.src) 411 .width('0%').height('0%') 412 .onComplete( 413 () => { 414 performTask(); 415 }) 416 } 417 .width('100%') 418 } 419 } 420} 421``` 422 423 424### 效果展示 425 426| 段落样式设置(断词策略、文本对齐方式、最大行数限制) | 效果示意 | 427| -------- | -------- | 428| 文本对齐方式为text.TextAlign.LEFT,最大行数为3,断词策略为text.WordBreak.BREAK_WORD。 |  | 429| 文本对齐方式为text.TextAlign.RIGHT,最大行数为3,断词策略为text.WordBreak.BREAK_WORD。 |  | 430| 文本对齐方式为text.TextAlign.LEFT,最大行数为3,断词策略为text.WordBreak.BREAK_ALL。 |  | 431| 文本对齐方式为text.TextAlign.LEFT ,最大行数为10 ,断词策略为text.WordBreak.BREAK_ALL。 |  | 432 433 434## 多样式文本绘制与显示 435 436除基本文字、排版属性之外,针对应用中不同文本的设计,开发者可能需要设置使用不同的绘制样式或能力,以凸显对应文本的独特表现或风格,此时可以结合使用多种绘制样式进行文本的渲染。 437 438当前支持的多样式绘制及各绘制样式侧重效果如下: 439 440- **装饰线样式绘制:** 主要通过不同的线条样式对文本进行装饰,可以使文本更加突出,富有表现力。 441 442- **字体特性绘制:** 主要通过字体的变化,包括粗细、斜体等特性来改变文本的外观,增强文本的可读性和美观性。 443 444- **可变字体绘制:** 对应提供文本在不同的显示环境和设备上灵活灵活调整的能力,可满足更为精细的视觉效果。 445 446- **文本阴影绘制:** 主要通过在文本周围添加阴影效果,以提升文本的层次感和立体感,从而使文本更具吸引力。 447 448- **占位符绘制:** 可以在不确定文本内容时保持文本布局的稳定性,使得文本显示更为流畅和自然。 449 450### 装饰线 451 452装饰线([Decoration](../reference/apis-arkgraphics2d/js-apis-graphics-text.md#decoration))是指在文本上方、下方或中间添加的装饰性线条,当前支持上划线、下划线、删除线。 453 454可以通过添加文本装饰线,提升文本的视觉效果和可读性。 455 456使用装饰线需要初始化装饰线样式对象,并添加到文本样式中,从而在文本绘制时生效。 457 458### 字体特征 459 460**字体特征**([FontFeature](../reference/apis-arkgraphics2d/js-apis-graphics-text.md#fontfeature))绘制专注于在文本渲染过程中对字体特性(如粗体、斜体、字体变种等)的处理,允许字体在不同的排版场景下表现出不同的效果,可用于增强文本的表现力,使其更符合设计和阅读需求。 461 462常见的**FontFeature**包含有liga、frac、case等,需要对应的ttf文件支持才能正常使能。 463 464### 可变字体 465 466**可变字体**([FontVariation](../reference/apis-arkgraphics2d/js-apis-graphics-text.md#fontvariation))是一种在一个字体文件中包含多个字形变体的字体格式,允许在一个字体文件内灵活地调整字体的各种属性(如字重、字宽、斜体等)。 467 468与传统字体文件(每种变体需要一个独立的文件)不同,可变字体在一个字体文件中包含多个变体轴,可通过使用可变字体实现文本渲染绘制时的平滑过渡。 469 470### 文本阴影 471 472**文本阴影**([TextShadow](../reference/apis-arkgraphics2d/js-apis-graphics-text.md#textshadow))为文本提供了深度感,使得文本在背景上更具立体感。通常用于提升文本的视觉吸引力或增强可读性,尤其是在色彩对比度较低的场景下。 473 474其中,TesxtShadow有三个属性,分别为阴影颜色color、阴影基于当前文本的偏移位置point、阴影半径blurRadius。 475 476使用阴影效果需要在文本样式中设置对应的阴影效果数组,从而在文本绘制时生效。 477 478### 占位符 479 480占位符绘制用于处理文本中占位符符号的渲染。 481 482占位符也是用来实现图文混排的关键,是指在实际图像或内容注册之前,用来预先提供货替代某个位置的视觉元素。 483 484### 开发步骤 485 4861. 通过context获取到Canvas画布对象。 487 488 ```ts 489 // 绘制代码逻辑写在这里 490 let canvas = context.canvas; 491 ``` 492 4932. 初始化文本样式。 494 495 ```ts 496 // 初始化装饰线对象 497 let decorations: text.Decoration = 498 { 499 // 装饰线类型,支持上划线、下划线、删除线 500 textDecoration: text.TextDecorationType.UNDERLINE, 501 // 装饰线颜色 502 color: { 503 alpha: 255, 504 red: 255, 505 green: 0, 506 blue: 0 507 }, 508 // 装饰线样式,支持波浪,虚线,直线等 509 decorationStyle:text.TextDecorationStyle.SOLID, 510 // 装饰线的高度 511 decorationThicknessScale: 1 512 }; 513 514 let myTextStyle: text.TextStyle = { 515 color: { 516 alpha: 255, 517 red: 255, 518 green: 0, 519 blue: 0 520 }, 521 fontSize: 300, 522 // 设置装饰线 523 decoration: decorations, 524 // 可变字体 525 fontVariations: [{axis: 'wght', value: 555}], 526 // 文本阴影 527 textShadows: [{color: { alpha: 0xFF, red: 0xFF, green: 0x00, blue: 0x00 }, point: {x:10,y:10}, blurRadius: 10}], 528 // 开启字体特征 529 fontFeatures: [{name: 'frac', value: 1}] 530 }; 531 ``` 532 5333. 初始化段落样式。 534 535 ```ts 536 let myParagraphStyle: text.ParagraphStyle = { 537 textStyle: myTextStyle 538 }; 539 ``` 540 5414. 初始化段落对象,并添加占位符和文本。 542 543 ```ts 544 let fontCollection = text.FontCollection.getGlobalInstance(); 545 let ParagraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection); 546 547 // 初始化占位符对象 548 let myPlaceholderSpan: text.PlaceholderSpan = { 549 width: 300,//宽度 550 height: 300,//高度 551 align: text.PlaceholderAlignment.BOTTOM_OF_ROW_BOX, //基线对齐策略 552 baseline: text.TextBaseline.ALPHABETIC,//使用的文本基线类型 553 baselineOffset: 100//相比基线的偏移量。只有对齐策略是OFFSET_AT_BASELINE时生效 554 }; 555 // 添加占位符 556 ParagraphGraphBuilder.addPlaceholder(myPlaceholderSpan) 557 558 // 更新文本样式 559 ParagraphGraphBuilder.pushStyle(myTextStyle); 560 // 添加文本 561 ParagraphGraphBuilder.addText("1/2 1/3 1/4 "); 562 ``` 563 5645. 排版段落并进行文本绘制。 565 566 ```ts 567 //生成段落 568 let paragraph = ParagraphGraphBuilder.build(); 569 // 布局 570 paragraph.layoutSync(1250); 571 // 绘制文本 572 paragraph.paint(canvas, 0, 0); 573 ``` 574 5756. 绘制占位符所在的内容。 576 577 ```ts 578 let placeholderRects = paragraph.getRectsForPlaceholders();//获取全部占位符的数组 579 let left = placeholderRects[0].rect.left//获取第一个占位符的左边界 580 let top = placeholderRects[0].rect.top//获取第一个占位符的上边界 581 let right = placeholderRects[0].rect.right//获取第一个占位符的有边界 582 let bottom = placeholderRects[0].rect.bottom//获取第一个占位符的下边界 583 let pen: drawing.Pen = new drawing.Pen() 584 let pen_color : common2D.Color = { alpha: 0xFF, red: 0xFF, green: 0x00, blue: 0x00 } 585 pen.setColor(pen_color) 586 canvas.attachPen(pen) 587 canvas.drawRect(left,top,right,bottom)//使用draw方法绘制占位符矩形框 588 ``` 589 590 591### 完整示例 592 593```ts 594import { NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI' 595import { UIContext } from '@kit.ArkUI' 596import { drawing } from '@kit.ArkGraphics2D' 597import { text } from '@kit.ArkGraphics2D' 598import { image } from '@kit.ImageKit' 599import { common2D } from '@kit.ArkGraphics2D' 600 601// 创建一个MyRenderNode类,并绘制文本。 602class MyRenderNode extends RenderNode { 603 async draw(context: DrawContext) { 604 // 绘制代码逻辑写在这里 605 let canvas = context.canvas; 606 607 // 初始化装饰线对象 608 let decorations: text.Decoration = 609 { 610 // 装饰线类型,支持上划线、下划线、删除线 611 textDecoration: text.TextDecorationType.UNDERLINE, 612 // 装饰线颜色 613 color: { 614 alpha: 255, 615 red: 255, 616 green: 0, 617 blue: 0 618 }, 619 // 装饰线样式,支持波浪,虚线,直线等 620 decorationStyle:text.TextDecorationStyle.SOLID, 621 // 装饰线的高度 622 decorationThicknessScale: 1 623 }; 624 625 let myTextStyle: text.TextStyle = { 626 color: { 627 alpha: 255, 628 red: 255, 629 green: 0, 630 blue: 0 631 }, 632 fontSize: 300, 633 // 设置装饰线 634 decoration: decorations, 635 // 可变字体 636 fontVariations: [{axis: 'wght', value: 555}], 637 // 文本阴影 638 textShadows: [{color: { alpha: 0xFF, red: 0xFF, green: 0x00, blue: 0x00 }, point: {x:10,y:10}, blurRadius: 10}], 639 // 开启字体特征 640 fontFeatures: [{name: 'frac', value: 1}] 641 }; 642 643 let myParagraphStyle: text.ParagraphStyle = { 644 textStyle: myTextStyle 645 }; 646 647 let fontCollection = text.FontCollection.getGlobalInstance(); 648 let ParagraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection); 649 650 // 初始化占位符对象 651 let myPlaceholderSpan: text.PlaceholderSpan = { 652 width: 300,//宽度 653 height: 300,//高度 654 align: text.PlaceholderAlignment.BOTTOM_OF_ROW_BOX, //基线对齐策略 655 baseline: text.TextBaseline.ALPHABETIC,//使用的文本基线类型 656 baselineOffset: 100//相比基线的偏移量。只有对齐策略是OFFSET_AT_BASELINE时生效 657 }; 658 // 添加占位符 659 ParagraphGraphBuilder.addPlaceholder(myPlaceholderSpan) 660 661 // 更新文本样式 662 ParagraphGraphBuilder.pushStyle(myTextStyle); 663 // 添加文本 664 ParagraphGraphBuilder.addText("1/2 1/3 1/4 "); 665 666 // 生成段落 667 let paragraph = ParagraphGraphBuilder.build(); 668 // 布局 669 paragraph.layoutSync(1250); 670 // 绘制文本 671 paragraph.paint(canvas, 0, 0); 672 673 let placeholderRects = paragraph.getRectsForPlaceholders();//获取全部占位符的数组 674 let left = placeholderRects[0].rect.left// 获取第一个占位符的左边界 675 let top = placeholderRects[0].rect.top// 获取第一个占位符的上边界 676 let right = placeholderRects[0].rect.right// 获取第一个占位符的有边界 677 let bottom = placeholderRects[0].rect.bottom// 获取第一个占位符的下边界 678 let pen: drawing.Pen = new drawing.Pen() 679 let pen_color : common2D.Color = { alpha: 0xFF, red: 0xFF, green: 0x00, blue: 0x00 } 680 pen.setColor(pen_color) 681 canvas.attachPen(pen) 682 canvas.drawRect(left,top,right,bottom)// 使用draw方法绘制占位符矩形框 683 } 684} 685 686// 创建一个MyRenderNode对象 687const textNode = new MyRenderNode() 688// 定义newNode的像素格式 689textNode.frame = { 690 x: 0, 691 y: 100, 692 width: 1250, 693 height: 800 694} 695textNode.pivot = { x: 0.2, y: 0.8 } 696textNode.scale = { x: 1, y: 1 } 697 698class MyNodeController extends NodeController { 699 private rootNode: FrameNode | null = null; 700 701 makeNode(uiContext: UIContext): FrameNode { 702 this.rootNode = new FrameNode(uiContext) 703 if (this.rootNode == null) { 704 return this.rootNode 705 } 706 const renderNode = this.rootNode.getRenderNode() 707 if (renderNode != null) { 708 renderNode.frame = { 709 x: 0, 710 y: 0, 711 width: 10, 712 height: 500 713 } 714 renderNode.pivot = { x: 50, y: 50 } 715 } 716 return this.rootNode 717 } 718 719 addNode(node: RenderNode): void { 720 if (this.rootNode == null) { 721 return 722 } 723 const renderNode = this.rootNode.getRenderNode() 724 if (renderNode != null) { 725 renderNode.appendChild(node) 726 } 727 } 728 729 clearNodes(): void { 730 if (this.rootNode == null) { 731 return 732 } 733 const renderNode = this.rootNode.getRenderNode() 734 if (renderNode != null) { 735 renderNode.clearChildren() 736 } 737 } 738} 739 740let myNodeController: MyNodeController = new MyNodeController() 741 742async function performTask() { 743 myNodeController.clearNodes() 744 myNodeController.addNode(textNode) 745} 746 747@Entry 748@Component 749struct Font08 { 750 @State src: Resource = $r('app.media.startIcon') 751 build() { 752 Column() { 753 Row() { 754 NodeContainer(myNodeController) 755 .height('100%') 756 .width('100%') 757 Image(this.src) 758 .width('0%').height('0%') 759 .onComplete( 760 () => { 761 performTask(); 762 }) 763 } 764 .width('100%') 765 } 766 } 767} 768``` 769 770 771### 效果展示 772 773| 样式设置(装饰线样式、可变字体、文本阴影、字体特征、占位符) | 示意效果 | 774| -------- | -------- | 775| 不开启装饰线、可变字体、文本阴影、字体特征,不添加占位符。 |  | 776| 开启装饰线、可变字体、文本阴影、字体特征,添加占位符。 |  | 777