如何用平滑的边缘剪辑 BackdropFilter?

How to clip the BackdropFilter with smooth edges?

我想在 Flutter 中的图像上应用 BackdropFilter。因此,我使用以下方式应用 Flutter docs.

中给出的过滤器
import 'dart:ui';
import 'package:flutter/material.dart';

void main() {
   runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: MyApp(),
      ),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Stack(
          alignment: Alignment.bottomCenter,
          children: <Widget>[
            Container(
              height: 500,
              child: Image.network('https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcQlXYdeEKhFq34sh8-0ZKC1uqCcVGgOzdW_ZRAqCBkWxG-oeCB1'),
            ),
            Positioned(
              top: 300,
              bottom: 0,
              left: 0,
              right: 0,
              child: ClipRect(
                child: BackdropFilter(
                  filter: ImageFilter.blur(sigmaX: 2, sigmaY: 10),
                  child: Container(
                    color: Colors.black.withOpacity(0),
                  ),
                ),
              ),
            ),
          ]
        ),
      ),
    );
  }
}

它产生了以下输出: Output of my code

我在 BackDropFilter 和图像之间遇到了困难。虽然,我想要它们之间的平滑边缘。

我怎样才能达到类似的效果 this?

对我来说最好的方法是在 BackdropFilter 上方使用 ShaderMask

不幸的是,由于引擎发生变化而停止工作:link

我在 flutter 上创建了一个 issue,希望他们能尽快解决这个错误。

我能够实现它,但这是一种出路,因为目前还没有办法直接实现它。 制作此功能以创建效果。 此函数将收到您要模糊处理的小部件列表。

List<Widget> buildBlurredImage(List<Widget> l) {
    List<Widget> list = [];
    list.addAll(l);
    double sigmaX = 0;
    double sigmaY = 0.1;
    for (int i = 100; i < 350; i += 5) {
     // 100 is the starting height of blur
     // 350 is the ending height of blur
      list.add(Positioned(
        top: i.toDouble(),
        bottom: 0,
        left: 0,
        right: 0,
        child: ClipRect(
          child: BackdropFilter(
            filter: ImageFilter.blur(
              sigmaX: sigmaX,
              sigmaY: sigmaY,
            ),
            child: Container(
              color: Colors.black.withOpacity(0),
            ),
          ),
        ),
      ));
      sigmaX += 0.1;
      sigmaY += 0.1;
    }
    return list;
  }

然后在你的小部件中 class 在堆栈中使用这样的函数

@override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Stack(
          alignment: Alignment.bottomCenter,
          // children: <Widget>[],
          children: buildBlurredImage([
            Container(
              height: 500,
              child: Image.network(
                'https://www.thewowstyle.com/wp-content/uploads/2015/02/Beautiful-Wallpapers-14.jpg',
                fit: BoxFit.cover,
              ),
            ),
          ]),
        ),
      ),
    );
  }

您的最终小部件 class 将如下所示

class MyApp extends StatelessWidget {
  List<Widget> buildBlurredImage(List<Widget> l) {
    List<Widget> list = [];
    list.addAll(l);
    double sigmaX = 0;
    double sigmaY = 0.1;
    for (int i = 100; i < 350; i += 5) {
      // 100 is the starting height of blur
      // 350 is the ending height of blur
      list.add(Positioned(
        top: i.toDouble(),
        bottom: 0,
        left: 0,
        right: 0,
        child: ClipRect(
          child: BackdropFilter(
            filter: ImageFilter.blur(
              sigmaX: sigmaX,
              sigmaY: sigmaY,
            ),
            child: Container(
              color: Colors.black.withOpacity(0),
            ),
          ),
        ),
      ));
      sigmaX += 0.1;
      sigmaY += 0.1;
    }
    return list;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Stack(
          alignment: Alignment.bottomCenter,
          // children: <Widget>[],
          children: buildBlurredImage([
            Container(
              height: 500,
              child: Image.network(
                'https://www.thewowstyle.com/wp-content/uploads/2015/02/Beautiful-Wallpapers-14.jpg',
                fit: BoxFit.cover,
              ),
            ),
          ]),
        ),
      ),
    );
  }
}