给 UI 加点"特效":模糊、提亮、效果级联

你有没有注意到,现在很多 APP 的 UI 都有一种"毛玻璃"效果?比如 iOS 的控制中心、华为的下拉通知栏,背景是模糊的,前景内容清晰,看起来特别有层次感。

或者你有没有想过,在展示 HDR 照片时,让照片的高光区域"亮起来",比普通内容更耀眼?

HarmonyOS 的 uiEffect 模块就能帮你实现这些效果。它提供了两大类效果:Filter(滤镜)VisualEffect(视觉效果),可以给 UI 组件添加模糊、提亮等各种实时效果。

导入模块

import { uiEffect } from "@kit.ArkGraphics2D";

两大效果类型

下面是 uiEffect 效果应用的整体流程:

模糊效果

HDR 提亮

背景模糊

前景模糊

创建 Filter 或 VisualEffect 实例

添加效果类型

调用 blur 方法设置半径

调用 hdrBrightnessRatio 设置倍数

效果级联:可叠加多个效果

选择应用位置

backgroundFilter 应用到背景

foregroundFilter 应用到前景

组件渲染时自动应用效果

在开始写代码之前,先理解一下 uiEffect 的两大分类:

  • Filter:滤镜效果,包括模糊(blur)和 HDR 提亮(hdrBrightnessRatio)。Filter 是作用在组件的"背景"或"前景"上的。
  • VisualEffect:视觉效果,目前主要是预留的扩展类。你可以通过 createEffect() 创建实例,然后挂载到组件上。

这两种效果可以"级联"——也就是说,你可以在一个 Filter 或 VisualEffect 实例上叠加多个效果,它们会按顺序依次生效。

第一步:创建效果实例

创建 Filter 实例:

let filter : uiEffect.Filter = uiEffect.createFilter()

创建 VisualEffect 实例:

let visualEffect : uiEffect.VisualEffect = uiEffect.createEffect()

这两个方法返回的都是"头节点",你可以在这个实例上链式调用各种效果方法。

第二步:添加模糊效果

模糊是 Filter 最常用的效果之一。调用 blur 方法就能给组件添加模糊:

// xxx.ts
import { uiEffect } from '@kit.ArkGraphics2D';

let filter: uiEffect.Filter = uiEffect.createFilter();
filter.blur(10);

@Entry
@Component
struct UIEffectFilterExample {
    build(){
        Column({ space: 15 }) {
            Text('UIEffectFilter').fontSize(20).width('75%').fontColor('#DCDCDC')
            Image($r('app.media.foreground'))
                .width(100)
                .height(100)
                .backgroundImage($r('app.media.background'))
                .backgroundImagePosition(Alignment.Center)
                .backgroundImageSize({ width: 90, height: 90 })
                .backgroundFilter(filter)
        }
        .height('100%')
        .width('100%')
    }
}

这段代码做了以下几件事:

  1. 创建了一个 Filter 实例。
  2. 调用 blur(10) 设置模糊半径为 10。半径越大,模糊效果越强;半径为 0 时没有模糊效果。
  3. 在组件上使用 .backgroundFilter(filter) 将这个 Filter 应用到组件的背景上。

模糊半径的选择:

  • 轻微模糊(5~15):适合做毛玻璃效果、背景虚化
  • 中等模糊(20~50):适合做景深效果、焦点突出
  • 强烈模糊(50+):适合做占位图、加载中的占位效果

backgroundFilter vs foregroundFilter:

  • .backgroundFilter(filter):效果作用在组件的背景上。比如你有一张背景图,加上模糊后,背景就变成毛玻璃了。
  • .foregroundFilter(filter):效果作用在组件的前景内容上。比如你有一个 Text 组件,加上模糊后,文字就变模糊了。

第三步:添加 HDR 提亮效果

从 API version 24 开始,Filter 支持 HDR 提亮效果。这个效果能让组件的内容在 HDR 屏幕上显示得更亮、更耀眼。

filter.hdrBrightnessRatio(2.0)

这行代码设置了 2 倍的提亮倍数。也就是说,组件内容的亮度会被提升到 SDR 参考白亮度的 2 倍。

使用 HDR 提亮的注意事项:

  1. 需要权限:调用这个方法需要 ohos.permission.HDR_BRIGHTNESS 权限,记得在 module.json5 里声明。
  2. 需要 HDR 渲染管线:提亮效果需要开启 HDR 渲染管线才能生效。如果设备硬件不支持 HDR,即使设置了也不会有效果。
  3. 有性能开销:HDR 提亮会带来一定的性能和功耗开销,建议只在已有 HDR 图片或视频的场景使用。
  4. 不建议嵌套使用:如果在多层组件上都设置了 HDR 提亮,可能会造成过曝现象。

提亮倍数的范围:

  • 最小值:1.0(等于不做任何处理)
  • 最大值:设备当前的最大亮度除以 SDR 参考白亮度
  • 设置小于 1.0 的值时,按 1.0 处理
  • 设置超过最大值的值时,按最大值处理

实际场景:做一个毛玻璃效果的音乐播放器

很多音乐播放器的背景是当前专辑封面的模糊版本。用 uiEffect 实现起来非常简单:

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

// 创建模糊滤镜
let blurFilter: uiEffect.Filter = uiEffect.createFilter();
blurFilter.blur(30);

@Entry
@Component
struct MusicPlayer {
  build() {
    Stack() {
      // 底层:专辑封面作为背景,加上模糊
      Image($r('app.media.album_cover'))
        .width('100%')
        .height('100%')
        .backgroundFilter(blurFilter)

      // 上层:播放控制界面
      Column() {
        // 专辑封面(清晰版)
        Image($r('app.media.album_cover'))
          .width(250)
          .height(250)

        // 播放按钮等...
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Center)
    }
    .width('100%')
    .height('100%')
  }
}

这里把模糊滤镜应用到背景图上,前景的专辑封面保持清晰,就能实现那种"背景虚化、前景突出"的视觉效果。

实际场景:HDR 照片展示

如果你要做一个照片展示 APP,支持 HDR 照片的"提亮"显示:

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

// 创建 HDR 提亮滤镜
let hdrFilter: uiEffect.Filter = uiEffect.createFilter();
hdrFilter.hdrBrightnessRatio(2.0);

@Entry
@Component
struct PhotoViewer {
  build() {
    Column() {
      Image($r('app.media.hdr_photo'))
        .width('100%')
        .height('80%')
        .backgroundFilter(hdrFilter)
    }
    .width('100%')
    .height('100%')
  }
}

这样 HDR 照片在支持 HDR 的设备上就能显示出更亮、更生动的效果。

效果级联:叠加多个效果

下面是效果级联的工作原理:

创建 Filter 实例

添加第一个效果: blur

添加第二个效果: hdrBrightnessRatio

按添加顺序依次生效

先执行模糊处理

再执行 HDR 提亮

输出最终视觉效果

uiEffect 的"级联"特性让你可以在一个 Filter 实例上叠加多个效果。比如你既要模糊又要提亮:

let filter: uiEffect.Filter = uiEffect.createFilter();
filter.blur(20);
filter.hdrBrightnessRatio(1.5);

效果会按添加的顺序依次生效。先模糊,再提亮。

小结

uiEffect 模块的核心就是两个方法:

  1. createFilter():创建 Filter 实例,可以添加模糊和 HDR 提亮效果。
  2. createEffect():创建 VisualEffect 实例,用于扩展更多视觉效果。

把创建出来的实例通过 .backgroundFilter().foregroundFilter() 应用到组件上,就能实现实时的视觉效果。

这个模块最大的价值是让你用很少的代码就能实现复杂的视觉效果,而且这些效果是系统级别的硬件加速,性能比自己用 Canvas 画要好得多。如果你的 APP 需要毛玻璃效果、背景虚化、HDR 提亮等功能,直接用 uiEffect 就对了。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐