欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Flutter實現(xiàn)動態(tài)高斯模糊的流程步驟

 更新時間:2023年11月06日 09:12:06   作者:易秋  
一個App加上高斯模糊會形成一種高級的感覺,本文將介紹如何制作一個根據(jù)背景內(nèi)容來動態(tài)高斯模糊,文中有詳細的代碼實現(xiàn)步驟,代碼示例講解的非常詳細,具有一定的參考價值,需要的朋友可以參考下

效果如下

實現(xiàn)思路

AppBar本質(zhì)上是一個Widget,我們不直接通過ScaffoldappBar屬性來設(shè)置AppBar,而是將我們需要的AppBar放在body屬性里面,至于為什么不能放在appBar屬性里面呢,最主要的原因是,ScaffoldappBar屬性是頂級組件,在appBar以外的任何組件都無法覆蓋或置于其下,而我們的主要實現(xiàn)思路是通過Stack組件的堆疊以及Positioned的位置設(shè)置來實現(xiàn)此效果

實現(xiàn)步驟

創(chuàng)建一個工程

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
    );
  }
}

創(chuàng)建自定義嵌套導航路由

App結(jié)構(gòu)構(gòu)建

為了使代碼更好的管理和維護,我們對頁面使用三層架構(gòu)模式,即分為state、logic、view三層,state層專注于數(shù)據(jù),logic專注于頁面的邏輯、view專注于頁面的顯示,這類似于Vue<template> <script> <style>分層模式

dependencies:
  flutter:
    sdk: flutter
  # 路由管理
  get: ^4.6.5
  # 屏幕適配工具
  flutter_screenutil: ^5.9.0

main.dart中更改為如下內(nèi)容

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get_navigation/src/root/get_material_app.dart';
import 'package:text/router/routeconfig.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
      designSize: const Size(720, 1080),
      minTextAdapt: true,
      splitScreenMode: true,
      builder: (context, child) {
        return GetMaterialApp(
          title: 'Flutter Demo',
          // 隱藏debug
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.blueGrey),
            useMaterial3: true,
          ),
          getPages: RouteConfig.getPages,
          // 初始化主頁
          initialRoute: RouteConfig.main,
        );
      },
    );
  }
}

在lib中創(chuàng)建如下文件夾及文件 

router文件夾的內(nèi)容

routeconfig.dart

import 'package:get/get.dart';
import 'package:text/pages/appmain/view.dart';

class RouteConfig {
  //主頁面
  static const String main = "/";

  static final List<GetPage> getPages = [
    GetPage(name: main, page: () => const AppMainPage()),
  ];
}

appmain文件夾的內(nèi)容

state.dart

class AppMainState {
  AppMainState();
}

logic.dart

import 'package:get/get.dart';
import 'state.dart';

class AppMainLogic extends GetxController {
  final AppMainState state = AppMainState();
}

view.dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'logic.dart';

class AppMainPage extends StatefulWidget {
  const AppMainPage({super.key});

  @override
  State<AppMainPage> createState() => _AppMainPageState();
}

class _AppMainPageState extends State<AppMainPage>
    with TickerProviderStateMixin {
  final logic = Get.put(AppMainLogic());
  final state = Get.find<AppMainLogic>().state;

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(),
    );
  }
}

mainrouteconfig.dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:text/pages/home/view.dart';

class NestedController extends GetxController {
  static const String home = "/homePage";
  static const String explore = "/explorePage";
  static const String musicLibrary = "/musicLibraryPage";

  static final Map<String, Widget> pages = {
    home: const HomePage(),
  };

  Route? onGenerateRoute(RouteSettings settings) {
    GetPageRoute? getPageRoute;
    pages.forEach((key, value) {
      if (settings.name == key) {
        getPageRoute = GetPageRoute(
          settings: settings,
          page: () => value,
          transition: Transition.fade,
        );
      }
    });

    return getPageRoute;
  }
}

home文件夾的內(nèi)容

state.dart

class HomeState {
  HomeState() {
    ///Initialize variables
  }
}

logic.dart

import 'package:get/get.dart';

import 'state.dart';

class HomeLogic extends GetxController {
  final HomeState state = HomeState();
}

view.dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';

import 'logic.dart';

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final logic = Get.put(HomeLogic());
  final state = Get.find<HomeLogic>().state;

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

創(chuàng)建完基礎(chǔ)App架構(gòu)模式后,我們開始自定義一個橋套導航,以便使我們在同一個頁面內(nèi)做頁面的跳轉(zhuǎn),這類似于TabBar的效果

接下來我們就可以使用我們的自定義嵌套導航了, 頁面的嵌套導航總管理在pages/appmain文件夾下的mainrouteconfig.dart,然后我們接著完成嵌套導航結(jié)構(gòu)

自定義嵌套導航

在需要用到嵌套導航的頁面引入如下代碼

Navigator(
                      key: Get.nestedKey(1),
                      initialRoute: NestedController.home,
                      onGenerateRoute: state.nestedController.onGenerateRoute,
                    )

如我們想在appmain下的view.dart中引入,首先state層建立我們需要的數(shù)據(jù),這里我使用了一個第三方的TabBar組件,大家想用官方的組件也可以,只需稍做修改即可

導入第三方組件依賴

dependencies:
  flutter:
    sdk: flutter
  # 路由管理
  get: ^4.6.5
  # 屏幕適配工具
  flutter_screenutil: ^5.9.0
  # bruno ui組件
  bruno: ^3.4.3

appmain/state.dart中修改如下

import 'package:bruno/bruno.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:text/pages/appmain/mainrouteconfig.dart';

class AppMainState {
  late List<BadgeTab> tabs; // Tab列表
  late TabController tabController; // Tab控制器

  late NestedController nestedController;

  AppMainState() {
    // 添加頂部tab
    tabs = [];
    tabs.add(BadgeTab(text: "首頁"));
    tabs.add(BadgeTab(text: "發(fā)現(xiàn)"));
    tabs.add(BadgeTab(text: "樂庫"));

    nestedController =
        Get.put(NestedController(), permanent: true); // 創(chuàng)建嵌套導航控制器
  }
}

appmain/logic.dart修改如下,這里的void brnTabBarOnTap(brnState, index)函數(shù)中多了兩個頁面,大家可以自行在pages創(chuàng)建另外兩個頁面,也可以根據(jù)自己的需求進行更改

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:text/pages/appmain/mainrouteconfig.dart';
import 'state.dart';

class AppMainLogic extends GetxController {
  final AppMainState state = AppMainState();

    void tabControllerInit(TickerProvider tickerProvider) {
    state.tabController =
        TabController(length: state.tabs.length, vsync: tickerProvider);
  }

  // 路由跳轉(zhuǎn)控制
  void brnTabBarOnTap(brnState, index) {
    brnState.refreshBadgeState(index);
    switch (index) {
      case 0:
        Get.toNamed(NestedController.home, id: 1, arguments: {});
      case 1:
        Get.toNamed(NestedController.explore, id: 1, arguments: {});
      case 2:
        Get.toNamed(NestedController.musicLibrary, id: 1, arguments: {});
    }
  }
}

我創(chuàng)建的頁面如下,內(nèi)容和home文件夾下的各文件類似,只是類名不同

然后在appmain/mainrouteconfig.dart中稍作修改

  static const String home = "/homePage";
  static const String explore = "/explorePage";
  static const String musicLibrary = "/musicLibraryPage";
 
  static final Map<String, Widget> pages = {
    home: const HomePage(),
    explore: const ExplorePage(),
    musicLibrary: const MusicLibraryPage(),
  };

然后我們就可以在appmain/view中使用了,為了更好的適配多分辨率屏幕的影響,我們可以先定義一個頁面縮放小工具,我們在lib目錄下創(chuàng)建一個common文件夾,文件夾下創(chuàng)建一個utils文件夾,里面有個工具類screenadaptor.dart

工具類內(nèi)容如下,此工具類是為了更好的管理橫豎屏的像素而建立的類

import 'package:flutter_screenutil/flutter_screenutil.dart';

class ScreenAdaptor {

  ScreenAdaptor();
  double getLengthByOrientation(double horizon, double vertical)
  {
    return ScreenUtil().orientation.index == 0 ? horizon : vertical;
  }
}

final ScreenAdaptor screenAdaptor = ScreenAdaptor();

這時,我們就可以在appmain/view.dart中添加嵌套導航的組件以及一些樣式的優(yōu)化,代碼如下

import 'package:bruno/bruno.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:text/common/utils/screenadaptor.dart';
import 'logic.dart';

class AppMainPage extends StatefulWidget {
  const AppMainPage({super.key});

  @override
  State<AppMainPage> createState() => _AppMainPageState();
}

class _AppMainPageState extends State<AppMainPage>
    with TickerProviderStateMixin {
  final logic = Get.put(AppMainLogic());
  final state = Get.find<AppMainLogic>().state;

  @override
  void initState() {
    super.initState();
    logic.tabControllerInit(this);
  }

    @override
  void dispose() {
    super.dispose();
    state.tabController.dispose();
    state.nestedController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ConstrainedBox(
        constraints: const BoxConstraints.expand(),
        child: Stack(
          children: [
            Positioned(
              // 不可以修改
              top: screenAdaptor.getLengthByOrientation(35.h, 35.h),
              child: SizedBox(
                width: ScreenUtil().screenWidth,
                height: ScreenUtil().screenHeight,
                child: Navigator(
                  key: Get.nestedKey(1),
                  initialRoute: "/homePage",
                  onGenerateRoute: state.nestedController.onGenerateRoute,
                ),
              ),
            ),
            Positioned(
              top: screenAdaptor.getLengthByOrientation(-10.h, -10.h),
              child: SizedBox(
                width: ScreenUtil().screenWidth,
                child: BrnAppBar(
                  // 狀態(tài)欄和底部欄樣式
                  systemOverlayStyle: const SystemUiOverlayStyle(
                    statusBarColor: Colors.transparent,
                    statusBarIconBrightness: Brightness.dark,
                    statusBarBrightness: Brightness.dark,
                    systemNavigationBarColor: Colors.transparent,
                  ),
                  primary: true,
                  // 不顯示底部分割線
                  showDefaultBottom: false,
                  backgroundColor: Colors.transparent,
                  title: BrnTabBar(
                    indicatorColor: Colors.transparent,
                    backgroundcolor: Colors.transparent,
                    padding: EdgeInsets.fromLTRB(
                        screenAdaptor.getLengthByOrientation(70.w, 160.w),
                        0,
                        screenAdaptor.getLengthByOrientation(70.w, 160.w),
                        0),
                    mode: BrnTabBarBadgeMode.origin,
                    controller: state.tabController,
                    tabs: state.tabs,
                    onTap: logic.brnTabBarOnTap,
                    labelStyle: const TextStyle(
                      backgroundColor: Colors.transparent,
                      fontWeight: FontWeight.bold,
                    ),
                    unselectedLabelStyle: const TextStyle(
                      backgroundColor: Colors.transparent,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  leadingWidth:
                      screenAdaptor.getLengthByOrientation(100.w, 50.w),
                  leading: IconButton(
                    onPressed: (){}, // 打開側(cè)邊欄
                    icon: const Icon(Icons.menu),
                  ),
                  themeData: BrnAppBarConfig(
                    itemSpacing: 0,
                    leftAndRightPadding: 0,
                  ),
                  actions: <Widget>[
                    IconButton(
                      onPressed: () {},
                      icon: const Icon(Icons.search),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

然后一運行,就可以發(fā)現(xiàn)大體效果出來了

有了AppBar框架后,我們就可以實現(xiàn)我們的動態(tài)高斯模糊了

高斯模糊

組件的背景高斯模糊我們可以通過BackdropFilter這一個類來做實現(xiàn),基于此,我封裝了一個類來便于我們使用

我們在lib目錄下新建一個component文件夾,里面創(chuàng)建一個BlurRectWidget的類

內(nèi)容為

import 'dart:ui';

import 'package:flutter/material.dart';

class BlurRectWidget extends StatelessWidget {
  final Widget _widget;
  final double singmaX;
  final double singmaY;

  const BlurRectWidget(this._widget, {super.key, required this.singmaX, required this.singmaY});

  @override
  Widget build(BuildContext context) {
    return ClipRRect(
      child: BackdropFilter(
        filter: ImageFilter.blur(
          sigmaX: singmaX,
          sigmaY: singmaY,
        ),
        child: _widget,
      ),
    );
  }
}

使用方法

BlurRectWidget(
                  singmaX: 20,
                  singmaY: 20,
                  widget // 這里換成你想包裹的widget
               )

比如我們在appmain/view.dart中將BrnAppBar包裹起來

BlurRectWidget(
                  singmaX: 20,
                  singmaY: 20,
                  BrnAppBar( ... )   
                ),

運行查看效果

可以看到已有高斯模糊效果,那是不是動態(tài)的呢,我們在home/view里面添加一些內(nèi)容來驗證

home/view.dart內(nèi)容修改如下

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:text/common/utils/screenadaptor.dart';

import 'logic.dart';

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final logic = Get.put(HomeLogic());
  final state = Get.find<HomeLogic>().state;

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.fromLTRB(
        screenAdaptor.getLengthByOrientation(24.h, 20.h),
        0,
        screenAdaptor.getLengthByOrientation(24.h, 20.h),
        0,
      ),
      child: Stack(
        children: [
          SizedBox(
            // 占滿屏幕
            width: ScreenUtil().screenWidth,
            height: ScreenUtil().screenHeight,
            child: ListView(
              children: [
                // 占位
                SizedBox(
                  height: screenAdaptor.getLengthByOrientation(45.h, 45.h),
                ),
                Container(
                  color: Colors.blue,
                  height: 1000,
                  width: 100,
                  child: Image.network(
                    "https://t.mwm.moe/mp/",
                    fit: BoxFit.cover,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

重新運行效果

可以看到已經(jīng)有了動態(tài)高斯模糊 自此高級觀感的AppBar已經(jīng)實現(xiàn)完畢

封裝BackdropFilter

為了能像使用CSS里的filter一樣方便,我封裝了一個BackdropCSSFilter類, 此類基于https://github.com/iofod/flutter_css_filter做修改,因為原作者的CSSFilter對組件進行模糊而不是對背景進行模糊,所以我做修改了

common/utils目錄下創(chuàng)建如下文件

base.dart內(nèi)容如下

import 'dart:math' as math;
import 'css_filter.dart';
import 'utils.dart';

class BackdropFilterMatrix {
  /// Check: https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/contrast()
  static contrast({required List<double> matrix, required double value}) {
    double v = value;
    double b = (1.0 - value) * 0.5 * 255.0; // 0.5*255 => 127

    return multiplyMatrix5(matrix, <double>[
      v,
      0,
      0,
      0,
      b,
      0,
      v,
      0,
      0,
      b,
      0,
      0,
      v,
      0,
      b,
      0,
      0,
      0,
      1,
      0,
      0,
      0,
      0,
      0,
      1
    ]);
  }

  /// Formula from: https://www.w3.org/TR/filter-effects-1/#grayscaleEquivalent
  static grayscale({required List<double> matrix, required double value}) {
    double v = 1.0 - value;
    double lumR = 0.2126;
    double lumG = 0.7152;
    double lumB = 0.0722;

    return multiplyMatrix5(matrix, <double>[
      (lumR + (1 - lumR) * v),
      (lumG - lumG * v),
      (lumB - lumB * v),
      0,
      0,
      (lumR - lumR * v),
      (lumG + (1 - lumG) * v),
      (lumB - lumB * v),
      0,
      0,
      (lumR - lumR * v),
      (lumG - lumG * v),
      (lumB + (1 - lumB) * v),
      0,
      0,
      0,
      0,
      0,
      1,
      0,
      0,
      0,
      0,
      0,
      1
    ]);
  }

  /// Formula from: https://www.w3.org/TR/filter-effects-1/#sepiaEquivalent
  static sepia({required List<double> matrix, required double value}) {
    double v = 1.0 - value;

    return multiplyMatrix5(matrix, <double>[
      (0.393 + 0.607 * v),
      (0.769 - 0.769 * v),
      (0.189 - 0.189 * v),
      0,
      0,
      (0.349 - 0.349 * v),
      (0.686 + 0.314 * v),
      (0.168 - 0.168 * v),
      0,
      0,
      (0.272 - 0.272 * v),
      (0.534 - 0.534 * v),
      (0.131 + 0.869 * v),
      0,
      0,
      0,
      0,
      0,
      1,
      0,
      0,
      0,
      0,
      0,
      1
    ]);
  }

  /// Check: https://www.geeksforgeeks.org/css-invert-function/
  static invert({required List<double> matrix, required double value}) {
    // v * (255 - n) + (1 - v) * n => (1 - 2v) * n + 255 * v
    double v = value * 255.0;
    double k = 1.0 - 2.0 * value;

    // The fifth column n is 255.
    return multiplyMatrix5(matrix, <double>[
      k,
      0,
      0,
      0,
      v,
      0,
      k,
      0,
      0,
      v,
      0,
      0,
      k,
      0,
      v,
      0,
      0,
      0,
      1,
      0,
      0,
      0,
      0,
      0,
      1
    ]);
  }

  /// Check: https://stackoverflow.com/questions/64639589/how-to-adjust-hue-saturation-and-brightness-of-an-image-in-flutter
  static hue({required List<double> matrix, required double value}) {
    double v = math.pi * (value / 180.0);
    double cosVal = math.cos(v);
    double sinVal = math.sin(v);
    double lumR = 0.213;
    double lumG = 0.715;
    double lumB = 0.072;

    return multiplyMatrix5(matrix, <double>[
      (lumR + (cosVal * (1 - lumR))) + (sinVal * (-lumR)),
      (lumG + (cosVal * (-lumG))) + (sinVal * (-lumG)),
      (lumB + (cosVal * (-lumB))) + (sinVal * (1 - lumB)),
      0,
      0,
      (lumR + (cosVal * (-lumR))) + (sinVal * 0.143),
      (lumG + (cosVal * (1 - lumG))) + (sinVal * 0.14),
      (lumB + (cosVal * (-lumB))) + (sinVal * (-0.283)),
      0,
      0,
      (lumR + (cosVal * (-lumR))) + (sinVal * (-(1 - lumR))),
      (lumG + (cosVal * (-lumG))) + (sinVal * lumG),
      (lumB + (cosVal * (1 - lumB))) + (sinVal * lumB),
      0,
      0,
      0,
      0,
      0,
      1,
      0,
      0,
      0,
      0,
      0,
      1
    ]);
  }

  static brightness({required List<double> matrix, required double value}) {
    double v = value;

    return multiplyMatrix5(matrix, <double>[
      v,
      0,
      0,
      0,
      0,
      0,
      v,
      0,
      0,
      0,
      0,
      0,
      v,
      0,
      0,
      0,
      0,
      0,
      1,
      0,
      0,
      0,
      0,
      0,
      1
    ]);
  }

  /// Check: https://docs.rainmeter.net/tips/colormatrix-guide/
  static saturate({required List<double> matrix, required double value}) {
    return BackdropFilterMatrix.grayscale(matrix: matrix, value: 1.0 - value);
  }

  static opacity({required List<double> matrix, required double value}) {
    return multiplyMatrix5(matrix, <double>[
      1,
      0,
      0,
      0,
      0,
      0,
      1,
      0,
      0,
      0,
      0,
      0,
      1,
      0,
      0,
      0,
      0,
      0,
      value,
      0,
      0,
      0,
      0,
      0,
      1
    ]);
  }
}

// Allows matrix multiplication.
final filterTypeMap = {
  'contrast': BackdropFilterMatrix.contrast,
  'grayscale': BackdropFilterMatrix.grayscale,
  'hueRotate': BackdropFilterMatrix.hue,
  'brightness': BackdropFilterMatrix.brightness,
  'saturate': BackdropFilterMatrix.saturate,
  'opacity': BackdropFilterMatrix.opacity,
};

// Not superimposed on the original matrix.
final filterAloneMap = {
  'sepia': BackdropCSSFilter.sepia,
  'invert': BackdropCSSFilter.invert,
  'blur': BackdropCSSFilter.blur
};

css_filter.dart

/// CSS filter for flutter
/// Author: qkorbit
/// Released under BSD-3-Clause License.
library css_filter;

export 'filter.dart';
export 'presets.dart';
export 'base.dart' show BackdropFilterMatrix;
export 'utils.dart' show BackdropCSSFilterMatrix;

filter.dart

import 'dart:ui';
import 'package:flutter/material.dart';
import 'utils.dart';
import 'base.dart';

/// Use CSS filter effects on flutter's Widget. All CSS filters are implemented except `drop-shadow()`.
/// `drop-shadow()` should be replaced by the [BoxShadow](https://api.flutter.dev/flutter/painting/BoxShadow-class.html) or [Shadow](https://api.flutter.dev/flutter/dart-ui/Shadow-class.html) widget.
///
/// Example:
///
/// ```dart
/// CSSFilter.contrast(child: const Text('foo'), value: 1.2);
/// ```
///
/// Support effects:
/// * contrast()
/// * grayscale()
/// * sepia()
/// * hueRotate()
/// * brightness()
/// * saturate()
/// * invert()
/// * blur()
/// * opacity()
class BackdropCSSFilter {
  /// Adjusts the contrast of the input widget.
  /// A value under 1.0 decreases the contrast, while a value over 1.0 increases it.
  /// A value of 0.0 will make it completely gray.
  /// Default value is 1.0.
  static Widget contrast({required Widget child, required double value}) {
    if (!isNotDefault(value)) return child;

    return execFilterSample(
        BackdropFilterMatrix.contrast(matrix: baseMatrix(), value: value),
        child);
  }

  /// Converts the input widget to grayscale.
  /// Values between 0.0 and 1.0 are linear multipliers on the effect.
  /// A value of 1.0 is completely grayscale.
  /// Default value is 0.0.
  static Widget grayscale({required Widget child, required double value}) {
    if (!isNotNegative(value)) return child;

    return execFilterSample(
        BackdropFilterMatrix.grayscale(matrix: baseMatrix(), value: value),
        child);
  }

  /// Converts the input widget to sepia, giving it a warmer, more yellow/brown appearance.
  /// Values between 0.0 and 1.0 are linear multipliers on the effect.
  /// A value of 1.0 is completely sepia.
  /// Default value is 0.0.
  static Widget sepia({required Widget child, required double value}) {
    if (!isNotNegative(value)) return child;

    return execFilterSample(
        BackdropFilterMatrix.sepia(matrix: baseMatrix(), value: value), child);
  }

  /// Rotates the [hue](https://en.wikipedia.org/wiki/Hue) of the input widget.
  /// A positive hue rotation increases the hue value, while a negative rotation decreases the hue value.
  /// @parmas value: A value of rotate angle.
  /// Default value is 0.0.
  static Widget hueRotate({required Widget child, required double value}) {
    if (value == 0.0) return child;

    return execFilterSample(
        BackdropFilterMatrix.hue(matrix: baseMatrix(), value: value), child);
  }

  /// Apply a linear multiplier to the input widget, making it appear brighter or darker.
  /// A value under 1.0 darkens the Widget, while a value over 1.0 brightens it.
  /// A value of 0.0 will make it completely black.
  /// Default value is 1.0.
  static Widget brightness({required Widget child, required double value}) {
    if (!isNotDefault(value)) return child;

    return execFilterSample(
        BackdropFilterMatrix.brightness(matrix: baseMatrix(), value: value),
        child);
  }

  /// Super-saturates or desaturates the input widget.
  /// A value under 1.0 desaturates the Widget, while a value over 1.0 super-saturates it.
  /// A value of 0.0 is completely unsaturated.
  /// Default value is 1.0.
  static Widget saturate({required Widget child, required double value}) {
    if (!isNotDefault(value)) return child;

    return execFilterSample(
        BackdropFilterMatrix.saturate(matrix: baseMatrix(), value: value),
        child);
  }

  /// Inverts the color of input widget.
  /// Values between 0.0 and 1.0 are linear multipliers on the effect.
  /// A value of 1.0 is completely inverted.
  /// Default value is 0.0.
  static Widget invert({required Widget child, required double value}) {
    if (!isNotNegative(value)) return child;

    return execFilterSample(
        BackdropFilterMatrix.invert(matrix: baseMatrix(), value: value), child);
  }

  /// Apply a Gaussian blur to the input widget.
  /// A larger value will create more blur on input widget.
  /// @parmas value: A value of blur radius.
  /// Default value is 0.0.
  static Widget blur({required Widget child, required double value}) {
    if (!isNotNegative(value)) return child;

    return ClipRRect(
      child: BackdropFilter(
          filter: ImageFilter.blur(
              sigmaX: value, sigmaY: value, tileMode: TileMode.decal),
          child: child),
    );
  }

  /// Apply transparency to input widget.
  /// Values between 0.0 and 1.0 are linear multipliers on the effect.
  /// A value of 0.0 is completely transparent.
  /// Default value is 1.0.
  static Widget opacity({required Widget child, required double value}) {
    if (!isNotDefault(value)) return child;

    return execFilterSample(
        BackdropFilterMatrix.opacity(matrix: baseMatrix(), value: value),
        child);
  }

  /// A quick and efficient way to apply multiple filters to the input widget.
  /// You can use any combination of these filter effects.
  ///
  /// Example:
  ///
  /// ```dart
  /// CSSFilter.apply(child: const Text('Hello World!'), value: CSSFilterMatrix().contrast(0.5).blur(3.0));
  /// CSSFilter.apply(child: const Text('Hello World!'), value: CSSFilterMatrix().brightness(1.2).saturate(1.5));
  /// ```
  ///
  static Widget apply(
      {required Widget child, required BackdropCSSFilterMatrix value}) {
    List<double> matrix = baseMatrix();
    Widget tree = child;
    bool canMerge = false;

    value.conf.forEach((K, V) {
      var fn = filterTypeMap[K];

      if (fn != null) {
        matrix = fn(matrix: matrix, value: V);
        canMerge = true;
      } else {
        // merge layers once
        if (canMerge) {
          tree = ClipRRect(
            child: BackdropFilter(
              filter: toColorFilterMatrix(matrix),
              child: tree,
            ),
          );

          canMerge = false;
        }

        var alone = filterAloneMap[K];

        tree = alone!(child: tree, value: V);
        // reset matrix
        matrix = baseMatrix();
      }
    });

    if (!canMerge) return tree;

    return ClipRRect(
      child: BackdropFilter(
        filter: toColorFilterMatrix(matrix),
        child: tree,
      ),
    );
  }
}

presets.dart

import 'package:flutter/material.dart';

import 'filter.dart';
import 'utils.dart';

/// Added more preset filter effects to CSSFilter.
/// The current version adds instagram filter package, the values mainly refer to [CSSgram](https://github.com/una/CSSgram), partly refer to [instagram.css](https://github.com/picturepan2/instagram.css).
///
/// Example:
///
/// ```dart
/// CSSFilterPresets.insAshby(child: const Text('foo'));
/// CSSFilterPresets.insHelena(child: const Text('bar'));
/// ```
///
/// Support effects:
/// * ins1977()
/// * ins1977V2()
/// * insAden()
/// * insAmaro()
/// * insAshby()
/// * insBrannan()
/// * insBrooklyn()
/// * insClarendon()
/// * insDogpatch()
/// * insEarlybird()
/// * insGingham()
/// * insHelena()
/// * insHudson()
/// * insInkwell()
/// * insInkwellV2()
/// * insJuno()
/// * insKelvin()
/// * insLark()
/// * insLofi()
/// * insLudwig()
/// * insMaven()
/// * insMayfair()
/// * insMoon()
/// * insMoonV2()
/// * insNashville()
/// * insNashvilleV2()
/// * insPerpetua()
/// * insPoprocket()
/// * insReyes()
/// * insRise()
/// * insSierra()
/// * insSkyline()
/// * insSlumber()
/// * insStinson()
/// * insSutro()
/// * insToaster()
/// * insToasterV2()
/// * insValencia()
/// * insVesper()
/// * insWalden()
/// * insWaldenV2()
/// * insWillow()
/// * insXpro2()
///
class CSSFilterPresets {
  /// A quick and efficient way to apply preset effects to the input widget.
  /// You can even adjust the intensity of the preset effects.
  ///
  /// Example:
  ///
  /// ```dart
  /// CSSFilterPresets.apply(
  ///   child: const Text('foo'),
  ///   value: CSSFilterPresets.insMaven,
  ///   strength: 0.6
  /// );
  /// ```
  ///
  /// If the input widget is transparent, then the `alphaBlending` parameter should be set to adjust the [Alpha Compositing](https://ciechanow.ski/alpha-compositing/) to avoid gross overlay of transparency.
  /// In general, `alphaBlending` is set to the same opacity value as the input widget. If the opacity of the input widget is unknown, the `alphaBlending` value is set according to the actual situation.
  ///
  static Widget apply(
      {required Widget child,
      required Function value,
      double strength = 1.0,
      double alphaBlending = 1.0}) {
    if (strength <= 0.0) return child;
    if (strength >= 1.0) strength = 1.0;

    Widget filtered = value(child: child);

    if (strength == 1.0) return filtered;
    if (alphaBlending > 1.0) alphaBlending = 1.0;
    if (alphaBlending < 0.0) alphaBlending = 0.0;

    Widget tree = Stack(children: [
      Positioned(child: child),
      Positioned(
          child:
              IgnorePointer(child: Opacity(opacity: strength, child: filtered)))
    ]);

    if (alphaBlending == 1.0) return tree;

    return Opacity(
        opacity: 1.0 - (1.0 - alphaBlending) * strength, child: tree);
  }

  static Widget origin({required Widget child}) {
    return child;
  }

  static Widget ins1977({required Widget child}) {
    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(243, 106, 188, 0.3)),
      blendMode: BlendMode.screen,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix().contrast(1.1).brightness(1.1).saturate(1.3)),
    );
  }

  static Widget ins1977V2({required Widget child}) {
    return BackdropCSSFilter.apply(
        child: child,
        value: BackdropCSSFilterMatrix().sepia(0.5).hueRotate(-30.0).saturate(1.4));
  }

  static Widget insAden({required Widget child}) {
    return ShaderMask(
      shaderCallback: execShaderLinearSample([
        const Color.fromRGBO(66, 10, 14, 0.2),
        const Color.fromRGBO(0, 0, 0, 0.0)
      ], Alignment.centerRight),
      blendMode: BlendMode.darken,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix()
              .hueRotate(-20.0)
              .contrast(0.9)
              .saturate(0.85)
              .brightness(1.2)),
    );
  }

  static Widget insAmaro({required Widget child}) {
    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(125, 105, 24, 0.2)),
      blendMode: BlendMode.overlay,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix()
              .sepia(0.35)
              .contrast(1.1)
              .brightness(1.2)
              .saturate(1.3)),
    );
  }

  static Widget insAshby({required Widget child}) {
    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(125, 105, 24, 0.35)),
      blendMode: BlendMode.lighten,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix().sepia(0.5).contrast(1.2).saturate(1.8)),
    );
  }

  static Widget insBrannan({required Widget child}) {
    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(161, 44, 199, 0.31)),
      blendMode: BlendMode.lighten,
      child: BackdropCSSFilter.apply(
          child: child, value: BackdropCSSFilterMatrix().sepia(0.5).contrast(1.4)),
    );
  }

  static Widget insBrooklyn({required Widget child}) {
    return ShaderMask(
      shaderCallback: execShaderRadialSample([
        const Color.fromRGBO(168, 223, 193, 0.4),
        const Color.fromRGBO(196, 183, 200, 1.0)
      ], [
        0.0,
        0.7
      ]),
      blendMode: BlendMode.overlay,
      child: BackdropCSSFilter.apply(
          child: child, value: BackdropCSSFilterMatrix().contrast(0.9).brightness(1.1)),
    );
  }

  static Widget insClarendon({required Widget child}) {
    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(127, 187, 227, 0.2)),
      blendMode: BlendMode.overlay,
      child: BackdropCSSFilter.apply(
          child: child, value: BackdropCSSFilterMatrix().contrast(1.2).saturate(1.35)),
    );
  }

  static Widget insDogpatch({required Widget child}) {
    return BackdropCSSFilter.apply(
        child: child,
        value: BackdropCSSFilterMatrix().sepia(0.35).saturate(1.1).contrast(1.5));
  }

  static Widget insEarlybird({required Widget child}) {
    return ShaderMask(
      shaderCallback: execShaderRadialSample([
        const Color.fromRGBO(208, 186, 142, 1.0),
        const Color.fromRGBO(54, 3, 9, 1.0),
        const Color.fromRGBO(29, 2, 16, 1.0)
      ], [
        0.2,
        0.85,
        1.0
      ]),
      blendMode: BlendMode.overlay,
      child: BackdropCSSFilter.apply(
          child: child, value: BackdropCSSFilterMatrix().contrast(0.9).sepia(0.2)),
    );
  }

  static Widget insGingham({required Widget child}) {
    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(230, 230, 250, 1.0)),
      blendMode: BlendMode.softLight,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix().brightness(1.05).hueRotate(-10.0)),
    );
  }

  static Widget insHelena({required Widget child}) {
    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(158, 175, 30, 0.25)),
      blendMode: BlendMode.overlay,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix()
              .sepia(0.5)
              .contrast(1.05)
              .brightness(1.05)
              .saturate(1.35)),
    );
  }

  static Widget insHudson({required Widget child}) {
    return ShaderMask(
      shaderCallback: execShaderRadialSample([
        const Color.fromRGBO(166, 177, 255, 0.5),
        const Color.fromRGBO(52, 33, 52, 0.5)
      ], [
        0.5,
        1.0
      ]),
      blendMode: BlendMode.multiply,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix().brightness(1.2).contrast(0.9).saturate(1.1)),
    );
  }

  static Widget insInkwell({required Widget child}) {
    return BackdropCSSFilter.apply(
        child: child,
        value: BackdropCSSFilterMatrix()
            .sepia(0.3)
            .contrast(1.1)
            .brightness(1.1)
            .grayscale(1.0));
  }

  static Widget insInkwellV2({required Widget child}) {
    return BackdropCSSFilter.apply(
        child: child,
        value:
        BackdropCSSFilterMatrix().brightness(1.25).contrast(0.85).grayscale(1.0));
  }

  static Widget insJuno({required Widget child}) {
    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(127, 187, 227, 0.2)),
      blendMode: BlendMode.overlay,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix()
              .sepia(0.35)
              .contrast(1.15)
              .brightness(1.15)
              .saturate(1.8)),
    );
  }

  static Widget insKelvin({required Widget child}) {
    Widget sub = ShaderMask(
        shaderCallback:
            execShaderDirectSample(const Color.fromRGBO(56, 44, 52, 1.0)),
        blendMode: BlendMode.colorDodge,
        child: child);

    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(183, 125, 33, 1.0)),
      blendMode: BlendMode.overlay,
      child: sub,
    );
  }

  static Widget insLark({required Widget child}) {
    return BackdropCSSFilter.apply(
        child: child,
        value: BackdropCSSFilterMatrix()
            .sepia(0.25)
            .contrast(1.2)
            .brightness(1.3)
            .saturate(1.25));
  }

  static Widget insLofi({required Widget child}) {
    return BackdropCSSFilter.apply(
        child: child, value: BackdropCSSFilterMatrix().saturate(1.1).contrast(1.5));
  }

  static Widget insLudwig({required Widget child}) {
    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(125, 105, 24, 0.1)),
      blendMode: BlendMode.overlay,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix()
              .sepia(0.25)
              .contrast(1.05)
              .brightness(1.05)
              .saturate(2.0)),
    );
  }

  static Widget insMaven({required Widget child}) {
    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(3, 230, 26, 0.2)),
      blendMode: BlendMode.hue,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix()
              .contrast(0.95)
              .brightness(0.95)
              .saturate(1.5)
              .sepia(0.25)),
    );
  }

  static Widget insMayfair({required Widget child}) {
    return ShaderMask(
      shaderCallback: execShaderRadialSample([
        const Color.fromRGBO(255, 255, 255, 0.32),
        const Color.fromRGBO(255, 200, 200, 0.24),
        const Color.fromRGBO(17, 17, 17, 0.4)
      ], const [
        0.0,
        0.0,
        0.6
      ]),
      blendMode: BlendMode.overlay,
      child: BackdropCSSFilter.apply(
          child: child, value: BackdropCSSFilterMatrix().contrast(1.1).saturate(1.1)),
    );
  }

  static Widget insMoon({required Widget child}) {
    Widget sub = ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(160, 160, 160, 1.0)),
      blendMode: BlendMode.softLight,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix().grayscale(1).contrast(1.1).brightness(1.1)),
    );

    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(56, 56, 56, 1.0)),
      blendMode: BlendMode.lighten,
      child: sub,
    );
  }

  static Widget insMoonV2({required Widget child}) {
    return BackdropCSSFilter.apply(
        child: child,
        value: BackdropCSSFilterMatrix()
            .brightness(1.4)
            .contrast(0.95)
            .saturate(0.0)
            .sepia(0.35));
  }

  static Widget insNashville({required Widget child}) {
    Widget sub = ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(247, 176, 153, 0.56)),
      blendMode: BlendMode.darken,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix()
              .sepia(0.2)
              .contrast(1.2)
              .brightness(1.05)
              .saturate(1.2)),
    );

    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(0, 70, 150, 0.4)),
      blendMode: BlendMode.lighten,
      child: sub,
    );
  }

  static Widget insNashvilleV2({required Widget child}) {
    return ShaderMask(
      shaderCallback: execShaderRadialSample([
        const Color.fromRGBO(128, 78, 15, 0.5),
        const Color.fromRGBO(128, 78, 15, 0.65)
      ]),
      blendMode: BlendMode.screen,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix()
              .sepia(0.25)
              .contrast(1.5)
              .brightness(0.9)
              .hueRotate(-15.0)),
    );
  }

  static Widget insPerpetua({required Widget child}) {
    return ShaderMask(
      shaderCallback: execShaderLinearSample([
        const Color.fromRGBO(0, 91, 154, 0.5),
        const Color.fromRGBO(230, 193, 61, 0.5)
      ], Alignment.bottomCenter),
      blendMode: BlendMode.softLight,
      child: child,
    );
  }

  static Widget insPoprocket({required Widget child}) {
    return ShaderMask(
      shaderCallback: execShaderRadialSample([
        const Color.fromRGBO(206, 39, 70, 0.75),
        const Color.fromRGBO(0, 0, 0, 1.0)
      ], const [
        0.4,
        0.8
      ]),
      blendMode: BlendMode.screen,
      child: BackdropCSSFilter.apply(
          child: child, value: BackdropCSSFilterMatrix().sepia(0.15).brightness(1.2)),
    );
  }

  static Widget insReyes({required Widget child}) {
    return BackdropCSSFilter.apply(
        child: child,
        value: BackdropCSSFilterMatrix()
            .sepia(0.75)
            .contrast(0.75)
            .brightness(1.25)
            .saturate(1.4));
  }

  static Widget insRise({required Widget child}) {
    Widget sub = ShaderMask(
      shaderCallback: execShaderRadialSample([
        const Color.fromRGBO(236, 205, 169, 0.15),
        const Color.fromRGBO(50, 30, 7, 0.4)
      ], [
        0.55,
        1.0
      ]),
      blendMode: BlendMode.multiply,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix()
              .brightness(1.05)
              .sepia(0.2)
              .contrast(0.9)
              .saturate(0.9)),
    );

    return ShaderMask(
      shaderCallback: execShaderRadialSample([
        const Color.fromRGBO(232, 197, 152, 0.48),
        const Color.fromRGBO(0, 0, 0, 0.0)
      ], [
        0.0,
        0.9
      ]),
      blendMode: BlendMode.overlay,
      child: sub,
    );
  }

  static Widget insSierra({required Widget child}) {
    return ShaderMask(
      shaderCallback: execShaderRadialSample([
        const Color.fromRGBO(128, 78, 15, 0.5),
        const Color.fromRGBO(0, 0, 0, 0.65)
      ]),
      blendMode: BlendMode.screen,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix()
              .sepia(0.25)
              .contrast(1.5)
              .brightness(0.9)
              .hueRotate(-15.0)),
    );
  }

  static Widget insSkyline({required Widget child}) {
    return BackdropCSSFilter.apply(
        child: child,
        value: BackdropCSSFilterMatrix()
            .sepia(0.15)
            .contrast(1.25)
            .brightness(1.25)
            .saturate(1.2));
  }

  static Widget insSlumber({required Widget child}) {
    Widget sub = ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(69, 41, 12, 0.4)),
      blendMode: BlendMode.lighten,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix().saturate(0.66).brightness(1.05)),
    );

    return ShaderMask(
        shaderCallback:
            execShaderDirectSample(const Color.fromRGBO(125, 105, 24, 0.5)),
        blendMode: BlendMode.softLight,
        child: sub);
  }

  static Widget insStinson({required Widget child}) {
    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(240, 149, 128, 0.2)),
      blendMode: BlendMode.softLight,
      child: BackdropCSSFilter.apply(
          child: child,
          value:
          BackdropCSSFilterMatrix().contrast(0.75).saturate(0.85).brightness(1.15)),
    );
  }

  static Widget insSutro({required Widget child}) {
    return ShaderMask(
      shaderCallback: execShaderRadialSample([
        const Color.fromRGBO(0, 0, 0, 0.0),
        const Color.fromRGBO(0, 0, 0, 0.5)
      ], const [
        0.5,
        0.9
      ]),
      blendMode: BlendMode.darken,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix()
              .sepia(0.4)
              .contrast(1.2)
              .brightness(0.9)
              .saturate(1.4)
              .hueRotate(-10.0)),
    );
  }

  static Widget insToaster({required Widget child}) {
    return ShaderMask(
      shaderCallback: execShaderRadialSample([
        const Color.fromRGBO(128, 78, 15, 1.0),
        const Color.fromRGBO(59, 0, 59, 1.0)
      ]),
      blendMode: BlendMode.screen,
      child: BackdropCSSFilter.apply(
          child: child, value: BackdropCSSFilterMatrix().contrast(1.3).brightness(0.9)),
    );
  }

  static Widget insToasterV2({required Widget child}) {
    return ShaderMask(
      shaderCallback: execShaderRadialSample([
        const Color.fromRGBO(128, 78, 15, 1.0),
        const Color.fromRGBO(0, 0, 0, 0.25)
      ]),
      blendMode: BlendMode.screen,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix()
              .sepia(0.25)
              .contrast(1.5)
              .brightness(0.95)
              .hueRotate(-15.0)),
    );
  }

  static Widget insValencia({required Widget child}) {
    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(58, 3, 57, 0.5)),
      blendMode: BlendMode.exclusion,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix().contrast(1.08).brightness(1.08).sepia(0.08)),
    );
  }

  static Widget insVesper({required Widget child}) {
    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(125, 105, 24, 0.25)),
      blendMode: BlendMode.overlay,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix()
              .sepia(0.35)
              .contrast(1.15)
              .brightness(1.2)
              .saturate(1.3)),
    );
  }

  static Widget insWalden({required Widget child}) {
    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(0, 68, 204, 0.3)),
      blendMode: BlendMode.screen,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix()
              .brightness(1.1)
              .hueRotate(-10.0)
              .sepia(0.3)
              .saturate(1.6)),
    );
  }

  static Widget insWaldenV2({required Widget child}) {
    return ShaderMask(
      shaderCallback:
          execShaderDirectSample(const Color.fromRGBO(229, 240, 128, 0.5)),
      blendMode: BlendMode.darken,
      child: BackdropCSSFilter.apply(
          child: child,
          value: BackdropCSSFilterMatrix()
              .sepia(0.35)
              .contrast(0.8)
              .brightness(1.25)
              .saturate(1.4)),
    );
  }

  static Widget insWillow({required Widget child}) {
    return BackdropCSSFilter.apply(
        child: child,
        value: BackdropCSSFilterMatrix()
            .brightness(1.2)
            .contrast(0.85)
            .saturate(0.05)
            .sepia(0.2));
  }

  static Widget insXpro2({required Widget child}) {
    return ShaderMask(
      shaderCallback: execShaderRadialSample([
        const Color.fromRGBO(230, 231, 224, 1.0),
        const Color.fromRGBO(43, 42, 161, 0.6)
      ], [
        0.4,
        1.1
      ]),
      blendMode: BlendMode.colorBurn,
      child: BackdropCSSFilter.apply(child: child, value: BackdropCSSFilterMatrix().sepia(0.3)),
    );
  }
}

utils.dart

import 'package:flutter/material.dart';

List<double> baseMatrix() {
  return <double>[
    1,
    0,
    0,
    0,
    0,
    0,
    1,
    0,
    0,
    0,
    0,
    0,
    1,
    0,
    0,
    0,
    0,
    0,
    1,
    0,
    0,
    0,
    0,
    0,
    1
  ];
}

/// Check: https://github.com/openkraken/kraken/blob/main/kraken/lib/src/css/filter.dart
/// Calc 5x5 matrix multiplication.
List<double> multiplyMatrix5(List<double> a, List<double> b) {
  if (a.length != b.length) {
    throw FlutterError('Matrix length should be same.');
  }

  if (a.length != 25) {
    throw FlutterError('Matrix5 size is not correct.');
  }

  var a00 = a[0];
  var a01 = a[1];
  var a02 = a[2];
  var a03 = a[3];
  var a04 = a[4];
  var a10 = a[5];
  var a11 = a[6];
  var a12 = a[7];
  var a13 = a[8];
  var a14 = a[9];
  var a20 = a[10];
  var a21 = a[11];
  var a22 = a[12];
  var a23 = a[13];
  var a24 = a[14];
  var a30 = a[15];
  var a31 = a[16];
  var a32 = a[17];
  var a33 = a[18];
  var a34 = a[19];
  var a40 = a[20];
  var a41 = a[21];
  var a42 = a[22];
  var a43 = a[23];
  var a44 = a[24];

  var b00 = b[0];
  var b01 = b[1];
  var b02 = b[2];
  var b03 = b[3];
  var b04 = b[4];
  var b10 = b[5];
  var b11 = b[6];
  var b12 = b[7];
  var b13 = b[8];
  var b14 = b[9];
  var b20 = b[10];
  var b21 = b[11];
  var b22 = b[12];
  var b23 = b[13];
  var b24 = b[14];
  var b30 = b[15];
  var b31 = b[16];
  var b32 = b[17];
  var b33 = b[18];
  var b34 = b[19];
  var b40 = b[20];
  var b41 = b[21];
  var b42 = b[22];
  var b43 = b[23];
  var b44 = b[24];

  return [
    a00 * b00 + a01 * b10 + a02 * b20 + a03 * b30 + a04 * b40,
    a00 * b01 + a01 * b11 + a02 * b21 + a03 * b31 + a04 * b41,
    a00 * b02 + a01 * b12 + a02 * b22 + a03 * b32 + a04 * b42,
    a00 * b03 + a01 * b13 + a02 * b23 + a03 * b33 + a04 * b43,
    a00 * b04 + a01 * b14 + a02 * b24 + a03 * b34 + a04 * b44,
    a10 * b00 + a11 * b10 + a12 * b20 + a13 * b30 + a14 * b40,
    a10 * b01 + a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41,
    a10 * b02 + a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42,
    a10 * b03 + a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43,
    a10 * b04 + a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44,
    a20 * b00 + a21 * b10 + a22 * b20 + a23 * b30 + a24 * b40,
    a20 * b01 + a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41,
    a20 * b02 + a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42,
    a20 * b03 + a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43,
    a20 * b04 + a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44,
    a30 * b00 + a31 * b10 + a32 * b20 + a33 * b30 + a34 * b40,
    a30 * b01 + a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41,
    a30 * b02 + a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42,
    a30 * b03 + a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43,
    a30 * b04 + a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44,
    a40 * b00 + a41 * b10 + a42 * b20 + a43 * b30 + a44 * b40,
    a40 * b01 + a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41,
    a40 * b02 + a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42,
    a40 * b03 + a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43,
    a40 * b04 + a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44,
  ];
}

ColorFilter toColorFilterMatrix(List<double> matrix) {
  return ColorFilter.matrix(matrix.sublist(0, 20));
}

Widget execFilterSample(List<double> matrix, Widget child) {
  return ClipRRect(
      child: BackdropFilter(filter: toColorFilterMatrix(matrix), child: child));
}

bool isNotNegative(double v) {
  return v > 0.0;
}

bool isNotDefault(double v) {
  return v != 1.0 && v >= 0.0;
}

execShaderDirectSample(Color color, [Alignment end = Alignment.centerRight]) {
  return (Rect bounds) {
    return LinearGradient(
        end: end,
        colors: [color, color],
        stops: const [0.0, 1.0]).createShader(bounds);
  };
}

execShaderLinearSample(List<Color> colors,
    [Alignment end = Alignment.centerRight,
    List<double> stops = const [0.0, 1.0]]) {
  return (Rect bounds) {
    return LinearGradient(end: end, colors: colors, stops: stops)
        .createShader(bounds);
  };
}

execShaderRadialSample(List<Color> colors,
    [List<double> stops = const [0.0, 1.0], radius = 0.8]) {
  return (Rect bounds) {
    return RadialGradient(
            center: Alignment.center,
            radius: radius,
            colors: colors,
            stops: stops
            // tileMode: TileMode.mirror,
            )
        .createShader(bounds);
  };
}

/// Generates the configuration for applying CSSFilter effects, which is provided to `CSSFilter.apply` for use.
/// Supports chain calls.
///
/// Example:
///
/// ```dart
/// CSSFilter.apply(
///   child: const Text('Hello World!'),
///   value: CSSFilterMatrix().contrast(1.5).sepia(0.4)
/// );
/// ```
class BackdropCSSFilterMatrix {
  Map conf = {};

  BackdropCSSFilterMatrix contrast([double value = 1.0]) {
    conf['contrast'] = value;
    return this;
  }

  BackdropCSSFilterMatrix grayscale([double value = 0.0]) {
    conf['grayscale'] = value;
    return this;
  }

  BackdropCSSFilterMatrix sepia([double value = 0.0]) {
    conf['sepia'] = value;
    return this;
  }

  BackdropCSSFilterMatrix hueRotate([double value = 0.0]) {
    conf['hueRotate'] = value;
    return this;
  }

  BackdropCSSFilterMatrix brightness([double value = 1.0]) {
    conf['brightness'] = value;
    return this;
  }

  BackdropCSSFilterMatrix saturate([double value = 1.0]) {
    conf['saturate'] = value;
    return this;
  }

  BackdropCSSFilterMatrix invert([double value = 0.0]) {
    conf['invert'] = value;
    return this;
  }

  BackdropCSSFilterMatrix blur([double value = 0.0]) {
    conf['blur'] = value;
    return this;
  }

  BackdropCSSFilterMatrix opacity([double value = 1.0]) {
    conf['opacity'] = value;
    return this;
  }
}

至此封裝完畢使用方法

BackdropCSSFilter.blur(
                  value: 10,
                  child: BrnAppBar( ... )   
                ),

效果同理

去除底部小白條

去除白條后的效果

以上就是基于Flutter實現(xiàn)動態(tài)高斯模糊的流程步驟的詳細內(nèi)容,更多關(guān)于Flutter動態(tài)高斯模糊的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論