You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Canvas实现BackdropFilter同款模糊效果?

用Canvas复刻BackdropFilter模糊效果的问题

我想在Flutter里用Canvas实现和BackdropFilter完全一致的模糊效果,参考的BackdropFilter实现代码如下:

ClipRect(
              child: BackdropFilter(
                filter: ui.ImageFilter.blur(sigmaX: 15, sigmaY: 15),
                child: Container(
                  width: 300,
                  height: 300,
                ),
              ),
            ),

我自己写的Canvas实现代码是这样的:

Paint paint = Paint()
      ..color = Colors.white
      ..imageFilter = ui.ImageFilter.blur(sigmaX: 15, sigmaY: 15)
      ..blendMode = BlendMode.srcOver;

但两种方式的效果完全不一样:

BackdropFilter的效果:
Effect with BackdropFilter

Canvas Paint的效果:
Effect with Painter


问题原因

BackdropFilter的逻辑是先模糊它下方的所有内容(背景),再在模糊后的背景上绘制透明容器;而你直接给Paint加imageFilter,是对当前绘制的白色矩形本身进行模糊——相当于把实心白色块模糊成扩散的灰色,和BackdropFilter的逻辑完全相反。

正确的Canvas实现方式

要复刻BackdropFilter的效果,需要先捕获要模糊的背景区域,对其模糊后再绘制到Canvas上,最后叠加透明容器:

  1. 先用RepaintBoundary包裹需要模糊的背景内容,通过GlobalKey捕获它:
final repaintKey = GlobalKey();

// 在Widget树中包裹背景
RepaintBoundary(
  key: repaintKey,
  child: // 你的背景内容(比如页面上的其他组件)
)
  1. 在CustomPainter的paint方法中,捕获背景图像并绘制模糊效果:
class CustomBlurPainter extends CustomPainter {
  final GlobalKey repaintKey;

  CustomBlurPainter(this.repaintKey);

  @override
  Future<void> paint(Canvas canvas, Size size) async {
    // 获取背景渲染对象并转换为图像
    final boundary = repaintKey.currentContext?.findRenderObject() as RenderRepaintBoundary?;
    final backgroundImage = await boundary?.toImage();
    if (backgroundImage == null) return;

    // 创建模糊画笔
    final blurPaint = Paint()
      ..imageFilter = ui.ImageFilter.blur(sigmaX: 15, sigmaY: 15);

    // 绘制模糊后的背景(只绘制需要的300x300区域)
    final blurRect = Rect.fromLTWH(0, 0, 300, 300);
    canvas.drawImageRect(
      backgroundImage,
      blurRect, // 从背景中截取的区域
      blurRect, // 绘制到Canvas的位置
      blurPaint,
    );

    // 叠加透明容器(和BackdropFilter中的Container对应,注意要加透明度)
    canvas.drawRect(
      blurRect,
      Paint()..color = Colors.white.withOpacity(0.5),
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

这样就能实现和BackdropFilter完全一致的模糊效果了——先模糊背景区域,再在上面叠加半透明白色容器。

内容的提问来源于stack exchange,提问作者giordy16

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 11:52:46