文档管理中心
您当前正在浏览新版开发者文档中心,目录分类和层级有所调整。点击左侧当前文档分类名称前的“☰”图标,可切换文档分类。 了解新版目录
问题处理与运维开发与测试问题应用框架开发UI框架组件使用如何实现文本颜色渐变

如何实现文本颜色渐变

问题现象

如何实现文本颜色从句首到句尾的渐变,且不被换行打断?

背景知识

  • linearGradient:HarmonyOS提供的一种通用属性,它用于实现组件的颜色线性渐变效果。
  • blendMode:一种与图像效果有关的属性,它常用于将当前控件的内容(包含子节点内容)与下方画布(可能为离屏画布)已有内容进行混合。
  • shaderStyle:显示为径向渐变RadialGradientStyle或线性渐变LinearGradientStyle或纯色ColorShaderStyle的效果,shaderStyle的优先级高于fontColor和AI识别,纯色建议使用fontColor。
  • LinearGradientStyle:显示为线性渐变。

解决方案

实现文本颜色渐变的方式及其适用场景内容如下:

展开

实现场景

实现方式

适用场景

文本渐变

linearGradient+blendMode裁切背景。

API20前。

文本渐变

shaderStyle设置线性渐变参数。

更简洁,仅支持API20+。

文本渐变流光效果

linearGradient+blendMode裁切背景+流光动画。

需流光效果的场景。

  • 方案一:通过linearGradient结合blendMode裁切背景,实现文本渐变。
    收起
    自动换行
    深色代码主题
    复制
    1. @Entry
    2. @Component
    3. struct Index {
    4. message: string = 'Hello World';
    5. build() {
    6. Row() {
    7. Column() {
    8. Row() {
    9. Text(this.message)
    10. .fontSize(50)
    11. .fontWeight(FontWeight.Bold)
    12. .blendMode(BlendMode.DST_IN, BlendApplyType.OFFSCREEN)
    13. }
    14. .linearGradient({
    15. direction: GradientDirection.Right,
    16. colors: [['#FFF563FF', 0.0], ['#FF0253EB', 0.2], ['#FF0253EB', 0.5], ['#FF26ECFF', 0.9]]
    17. })
    18. .blendMode(BlendMode.SRC_OVER, BlendApplyType.OFFSCREEN)
    19. }
    20. .width('100%')
    21. }
    22. .height('100%')
    23. }
    24. }

    运行效果:

  • 方案二:使用shaderStyle,通过Text组件的shaderStyle属性直接设置线性渐变参数。(仅支持API20+)
    收起
    自动换行
    深色代码主题
    复制
    1. @Entry
    2. @Component
    3. struct ExampleTwo {
    4. build() {
    5. Column() {
    6. Text('HarmonyOS')
    7. .fontSize(30)
    8. .shaderStyle({
    9. direction: GradientDirection.Right,
    10. colors: [['#FF0253EB', 0.0], ['#00ff00', 0.5], ['#0000ff', 1.0]]
    11. })
    12. }
    13. .width('100%')
    14. .height('100%')
    15. .justifyContent(FlexAlign.Center)
    16. }
    17. }

    运行效果:

  • 方案三:拓展功能实现。为背景渐变色添加动画,实现动态流光效果。
    收起
    自动换行
    深色代码主题
    复制
    1. @Entry
    2. @Component
    3. struct ExampleThree {
    4. message: string = 'Hello World';
    5. @State gradientPosition: number = 0;
    6. COLOR_START: string = '#FF26ECFF';
    7. COLOR_END: string = '#FF0253EB';
    8. build() {
    9. Row() {
    10. Column() {
    11. Row() {
    12. Text(this.message)
    13. .fontSize(50)
    14. .fontWeight(FontWeight.Bold)
    15. .blendMode(BlendMode.DST_IN, BlendApplyType.OFFSCREEN)
    16. }
    17. .linearGradient({
    18. direction: GradientDirection.Right,
    19. colors: [[this.COLOR_START, 0], [this.COLOR_END, this.gradientPosition], [this.COLOR_START, 1]]
    20. })
    21. .blendMode(BlendMode.SRC_OVER, BlendApplyType.OFFSCREEN)
    22. }
    23. .width('100%')
    24. .height('100%')
    25. .justifyContent(FlexAlign.Center)
    26. }
    27. .onAppear(() => {
    28. this.animateStart();
    29. })
    30. }
    31. private animateStart() {
    32. this.getUIContext().animateTo({
    33. duration: 2000,
    34. curve: Curve.Linear,
    35. iterations: 1,
    36. onFinish: () => {
    37. this.gradientPosition = 0;
    38. const COLOR_START = this.COLOR_START;
    39. const COLOR_END = this.COLOR_END;
    40. this.COLOR_START = COLOR_END;
    41. this.COLOR_END = COLOR_START;
    42. this.animateStart();
    43. }
    44. },
    45. () => {
    46. // 启动动画:修改gradientPosition触发渐变移动
    47. this.gradientPosition = 1;
    48. });
    49. }
    50. }

    运行效果:

常见FAQ

Q:如何使用linearGradient实现颜色在透明度上的渐变效果?

A:使用rgba格式的颜色来设置透明渐变的效果。

收起
自动换行
深色代码主题
复制
  1. @Entry
  2. @Component
  3. struct FAQ_1 {
  4. build() {
  5. Column() {
  6. }
  7. .height('10%')
  8. .width('100%')
  9. .linearGradient(
  10. {
  11. angle: 180,
  12. colors: [['rgba(128,128,128,0.5)', 0.1], ['rgba(128,128,128,0.3)', 0.6], ['rgba(128,128,128,0.0)', 1]]
  13. })
  14. }
  15. }

Q:设置linearGradient后,再设置backgroundColor,为何无效?

A:颜色渐变属于组件内容,绘制在背景上方,背景颜色是被覆盖了。设置了linearGradient渐变色,需要修改背景色为纯色,可以设置linearGradient的options的值为undefined,恢复为无线性渐变的效果。

收起
自动换行
深色代码主题
复制
  1. import { FrameNode, NodeController } from '@kit.ArkUI';
  2. class MyNodeController extends NodeController {
  3. makeNode(uiContext: UIContext): FrameNode | null {
  4. let box = new FrameNode(uiContext);
  5. box.commonAttribute.width(100).height(100).backgroundColor('#d1d3d5');
  6. let isBackgroundColor = false;
  7. box.commonAttribute.onClick(() => {
  8. isBackgroundColor = !isBackgroundColor;
  9. if (isBackgroundColor) {
  10. box.commonAttribute.backgroundColor('#d1d3d5');
  11. box.commonAttribute.linearGradient(undefined);
  12. } else {
  13. box.commonAttribute.linearGradient({ angle: 90, colors: [['#FF0253EB', 0], ['#FF26ECFF', 1]] });
  14. }
  15. });
  16. return box;
  17. }
  18. }
  19. @Entry
  20. @Component
  21. struct FrameNodeTypeTest {
  22. private myNodeController: MyNodeController = new MyNodeController();
  23. build() {
  24. Row() {
  25. NodeContainer(this.myNodeController);
  26. }
  27. }
  28. }