鴻蒙Next模糊介面梳理

olderciyuan發表於2024-11-17

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]}
          })

效果:


相關文章