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]}
})
效果: