鸿蒙Next模糊接口梳理

foregroundBlurStyle和backgroundBlurStyle

foregroundBlurStyle(value: BlurStyle, options?: ForegroundBlurStyleOptions)

backgroundBlurStyle(value: BlurStyle, options?: BackgroundBlurStyleOptions)

第一个参数都是模糊材质,用的是鸿蒙系统定制好的一套模糊参数,封装了模糊半径、蒙版颜色、饱和度、亮度四个参数(官方文档上说还封装了一个蒙版透明度参数,但从ArkUIRS的代码上来看其实只有这四个)。

第二个参数虽然类型不一样,一个前景一个背景,但都是继承自BlurStyleOptions,且目前都是只继承了,没有新增/修改任何属性,应该是为了方便后续新增一些差异化的参数而留的。

BlurStyleOptions的参数列表如下:

名称 参数类型 必填 描述
colorMode ThemeColorMode 模糊效果使用的深浅色模式。默认值:ThemeColorMode.SYSTEM
元服务API: 从API version 11开始,该接口支持在元服务中使用。
adaptiveColor AdaptiveColor 模糊效果使用的取色模式。默认值:AdaptiveColor.DEFAULT
元服务API: 从API version 11开始,该接口支持在元服务中使用。
blurOptions11+ BlurOptions 灰阶模糊参数。默认值:grayScale: [0,0]
元服务API: 从API version 12开始,该接口支持在元服务中使用。
scale12+ number 模糊效果程度。默认值:1.0取值范围:[0.0, 1.0]
元服务API: 从API version 12开始,该接口支持在元服务中使用。

具体实现细节:

  • colorMode配合BlurStyle决定一套基础模糊参数——模糊半径、蒙版颜色、饱和度、亮度;
  • 通过scale间接修改上述决定好的基础模糊参数,4种参数每种都会受到影响;
  • 如果colorMode != ThemeColorMode::SYSTEM,则灰阶不生效;
  • adaptiveColor决定是否使用取色模糊,AdaptiveColor.DEFAULT则不使用,直接取基础参数中的蒙版颜色;AdaptiveColor.AVERAGE则是启用取色模糊,将取色区域的颜色平均值作为蒙版颜色,更耗时。
std::shared_ptr<Rosen::RSFilter> CreateRSMaterialFilter(
    const BlurStyleOption& blurStyleOption, PipelineContext* pipeline)
{
    auto blurStyleTheme = pipeline->GetTheme<BlurStyleTheme>();
    if (!blurStyleTheme) {
        LOGW("cannot find theme of blurStyle, create blurStyle failed");
        return nullptr;
    }
    ThemeColorMode colorMode = blurStyleOption.colorMode;
    if (blurStyleOption.colorMode == ThemeColorMode::SYSTEM) {
        colorMode = GetResourceColorMode(pipeline) == ColorMode::DARK ? ThemeColorMode::DARK : ThemeColorMode::LIGHT;
    }
    auto blurParam = blurStyleTheme->GetBlurParameter(blurStyleOption.blurStyle, colorMode);
    CHECK_NULL_RETURN(blurParam, nullptr);
    auto ratio = blurStyleOption.scale;
    auto maskColor = blurParam->maskColor.BlendOpacity(ratio);
    auto radiusPx = blurParam->radius * pipeline->GetDipScale();
#ifndef USE_ROSEN_DRAWING
    auto radiusBlur = SkiaDecorationPainter::ConvertRadiusToSigma(radiusPx) * ratio;
#else
    auto radiusBlur = DrawingDecorationPainter::ConvertRadiusToSigma(radiusPx) * ratio;
#endif
    auto saturation = (blurParam->saturation - 1) * ratio + 1.0;
    auto brightness = (blurParam->brightness - 1) * ratio + 1.0;
    return Rosen::RSFilter::CreateMaterialFilter(radiusBlur, saturation, brightness, maskColor.GetValue(),
        static_cast<Rosen::BLUR_COLOR_MODE>(blurStyleOption.adaptiveColor));
}

backgroundBlurStyle特有的一些逻辑判断:

  • 会跟另一个模糊接口SetBackgroundEffect冲突,同时调用的话,二者只会生效一个;
  • 如果是对窗口设置,则在一定条件下将会不生效。
bool RosenRenderContext::UpdateBlurBackgroundColor(const std::optional<BlurStyleOption>& bgBlurStyle)
{
    if (!bgBlurStyle.has_value()) {
        return false;
    }
    bool blurEnable =
        bgBlurStyle->policy == BlurStyleActivePolicy::ALWAYS_ACTIVE ||  //设置为一直激活
        (bgBlurStyle->policy == BlurStyleActivePolicy::FOLLOWS_WINDOW_ACTIVE_STATE && bgBlurStyle->isWindowFocused);    //设置为需要激活但窗口失焦
    if (bgBlurStyle->isValidColor) {
        if (blurEnable) {
            rsNode_->SetBackgroundColor(GetBackgroundColor().value_or(Color::TRANSPARENT).GetValue());
        } else {
            rsNode_->SetBackgroundColor(bgBlurStyle->inactiveColor.GetValue());
        }
    }
    // 返回false不生效
    return blurEnable;
}

综上可以看出,这两个接口本质是对BlurStyle进行一个扩展,让使用者能够基于系统提供的模板做一些额外的调整,不过总体来说自由度还是有些受限。

foregroundEffect和backgroundEffect

foregroundEffect(options: ForegroundEffectOptions)

backgroundEffect(options: BackgroundEffectOptions)

看上去差不多,实际上天差地别,ForegroundEffectOptions只有radius一个参数;而BackgroundEffectOptions的参数列表则丰富得多,故此处只研究backgroundEffect

backgroundEffect的参数列表如下:

名称 类型 必填 说明
radius number 模糊半径,取值范围:[0, +∞),默认为0。
saturation number 饱和度,取值范围:[0, +∞),默认为1。推荐取值范围:[0, 50]。
brightness number 亮度,取值范围:[0, +∞),默认为1。推荐取值范围:[0, 2]。
color ResourceColor 蒙版颜色,默认透明色(0x00000000)。
adaptiveColor AdaptiveColor 背景模糊效果使用的取色模式,默认为DEFAULT。使用AVERAGE时color必须带有透明度,取色模式才生效(即默认颜色的情况下AVERAGE不生效)。
blurOptions BlurOptions 灰阶模糊参数,默认为[0,0]。

结合上面提到的BlurStyle和框架层代码可以看出,目前(API13)鸿蒙系统的模糊效果都是通过模糊半径、饱和度、亮度、蒙版颜色、取色模式、灰阶值这六个参数来决定的——有些接口只能调整一些参数;有些接口能自由调整所有参数;有些接口只能使用系统提供的定制参数。综上,无论哪个模糊接口、调用哪种参数类型,最后的实现其实都是改变这六个参数值。

个人认为效果比较好的一套参数:

          .backgroundEffect({
            radius: 100,
            saturation: 3,
            brightness: 1.2,
            blurOptions: {grayscale: [127,127]}
          })

效果:


posted @ 2024-11-17 22:26  olderciyuan  阅读(282)  评论(0)    收藏  举报