Flutter实现微信朋友圈高斯模糊效果
Posted 初一十五啊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter实现微信朋友圈高斯模糊效果相关的知识,希望对你有一定的参考价值。
1. 背景
最近一个需求改版UI视觉觉得微信朋友圈的边缘高斯模糊挺好看,然后就苦逼吭哧的尝试在Flutter
实现了,来看微信朋友圈点击展开的大图效果图:
微信朋友圈高斯模糊效果大概分4部分区域实现,如下图:
居中图片为原始图,然后背景模糊全图是原始图放大cover
模式的高斯模糊,在上下两个区域分别是两层单独处理边界的高斯模糊效果特殊处理,因此有时候可以看到微信朋友圈在上下两侧有明显分界线;
2. 实践
在Flutter
侧实现高斯模糊比较简单,可以直接使用系统的BackdropFilter
函数实现,需要传入一个filter
方式,然后对child
区域进行模糊过滤;
const BackdropFilter(
Key? key,
required this.filter,
Widget? child,
this.blendMode = BlendMode.srcOver,
) : assert(filter != null),
super(key: key, child: child);
Flutter
提供了简化ImageFiltered
实现高斯模糊,代码如下:
ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 20, sigmaY: 20),
child: Image.network(url,fit: BoxFit.cover, height: expandedHeight, width: width),
),
通过此方式,可以非常简约实现全屏高斯模糊~,现在难点是上下边界区域的边界模糊处理,这里需要使用一个ShaderMask
组件,在Flutter
侧ShaderMask
主要是实现渐变过渡能力的;
const ShaderMask(
Key? key,
required this.shaderCallback,
this.blendMode = BlendMode.modulate,
Widget? child,
) : assert(shaderCallback != null),
assert(blendMode != null),
super(key: key, child: child);
其需要shaderCallback
回调渐变Shader
,共提供3种渐变模式:
RadialGradient
:放射状渐变LinearGradient
:线性渐变SweepGradient
:扇形渐变
这里我们需要使用线性渐变LinearGradient
从上到下的渐变过渡,代码如下:
ShaderMask(
shaderCallback: (Rect bounds)
return const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.transparent,
Colors.white,
Colors.transparent
],
).createShader(bounds);
,
child: Image.network(url,
fit: BoxFit.cover, height: closeHeight, width: width),
)
就这样实现了?当我运行时候出现如下效果,效果还挺好的:
但是当我把封面图url
替换了一个浅色图片,却出现如下效果,中间区域变成了黑色的,看来是我想的简单了:
分析了下Flutter
线性过度源码,其将颜色进行过渡,
Color transparent = Color(0x00000000)
, 而
Color white = Color(0xFFFFFFFF)
,可以看到除了透明度之外,需要保证颜色不要发生大变化,其实我们诉求只是需要将透明度发生渐变即可,因此将Colors.white
改为Colors.black
,
ShaderMask(
shaderCallback: (Rect bounds)
return const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.transparent,
Colors.black,
Colors.transparent
],
).createShader(bounds);
,
child: Image.network(url,
fit: BoxFit.cover, height: closeHeight, width: width),
)
出现如下效果
这里颜色貌似符合预期,但是混合模式出现了问题,学过android
开发的一定属性如下这张BlendMode
混合模式图片:
ShaderMaster
默认的混合模式是BlendMode.modulate
,这个我也解释不清楚:这里有一篇相关文章juejin.cn/post/684490…
这里我们将混合模式替换为BlendMode.dstIn
:只显示src
和dst
重合部分,且src
的重合部分只有不透明度有用,经过这些操作后,整体效果最后如下所示:
最后奉上完整demo
的相关代码:
Widget buildCover(BuildContext context)
double width = MediaQuery.of(context).size.width;
double expandedHeight = 600;
double closeHeight = 300;
const String url =
'https://img.alicdn.com/imgextra/i2/O1CN01YWcPh81fbUvpcjUXp_!!6000000004025-2-tps-842-350.png';
return Container(
height: expandedHeight,
alignment: Alignment.center,
child: Stack(
children: [
ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 20, sigmaY: 20),
child: Image.network(url,
fit: BoxFit.cover, height: expandedHeight, width: width),
),
Container(
height: expandedHeight,
alignment: Alignment.center,
child: ShaderMask(
shaderCallback: (Rect bounds)
return const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.transparent,
Colors.black,
Colors.transparent
],
).createShader(bounds);
,
blendMode: BlendMode.dstIn,
child: Image.network(url,
fit: BoxFit.cover, height: closeHeight, width: width),
),
)
],
),
);
3. 总结
通过实践,发现Flutter
实现高斯模糊BackdropFilter/ImageFiltered
组件,渐变实现方式ShaderMask
,此外还需要掌握图形学的BlendMode
混合模式,以后在碰到类似需求时候建议直接砍了UI
视觉吧~~费劲~~~~
作者:上班多喝水
链接:https://juejin.cn/post/7126099548409167879
来源:稀土掘金
以上是关于Flutter实现微信朋友圈高斯模糊效果的主要内容,如果未能解决你的问题,请参考以下文章