foregroundBlurStyle和backgroundBlurStyle
foregroundBlurStyle(value: BlurStyle, options?: ForegroundBlurStyleOptions)
backgroundBlurStyle(value: BlurStyle, options?: BackgroundBlurStyleOptions)
第一個引數都是模糊材質,用的是鴻蒙系統定製好的一套模糊引數,封裝了模糊半徑、蒙版顏色、飽和度、亮度四個引數(官方文件上說還封裝了一個蒙版透明度引數,但從ArkUI
和RS
的程式碼上來看其實只有這四個)。
第二個引數雖然型別不一樣,一個前景一個背景,但都是繼承自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]}
})
效果: