Flutter特效插件thanos_snap_effect的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter特效插件thanos_snap_effect的使用

开始使用

thanos_snap_effect 是一个高性能、高度可定制且易于使用的Flutter特效插件,它实现了类似于《复仇者联盟3:无限战争》中Thanos打响指的效果。该插件允许开发者通过简单的配置和代码实现动画效果,并提供了丰富的自定义选项。

效果展示

以下是两个简单的示例,展示了如何使用 thanos_snap_effect 插件创建动画效果:

安装与配置

要开始使用此插件,首先需要在项目的 pubspec.yaml 文件中添加依赖项并包含着色器文件:

dependencies:
  thanos_snap_effect: ^latest_version # 替换为最新版本号

flutter:
  shaders:
    - packages/thanos_snap_effect/shader/thanos_snap_effect.glsl

使用方法

thanos_snap_effect 提供了一个名为 Snappable 的小部件,其用法类似于其他过渡小部件(如 FadeTransitionScaleTransition)。您只需要将目标小部件包裹在 Snappable 中,并传递一个 AnimationController 或任何从0.0到1.0的动画对象即可。

Snappable(
  animation: animationController, // AnimationController 对象,或任何其他具有从0.0到1.0双精度值变化的动画对象
  child: MyWidget(), // 您想要动画化的子组件
);

如果您想查看更复杂的例子,请参考官方示例

自定义效果

您可以根据需求调整粒子的行为,比如通过设置 outerPaddingstyle 属性来自定义 Snappable 小部件的效果。

Snappable(
  animation: _animationController,
  child: MyWidget(),
  outerPadding: const EdgeInsets.all(40.0), // 粒子出现范围的外边距,默认为 EdgeInsets.all(40.0)
  style: SnappableStyle(
    particleLifetime: 0.6, // 粒子存在时间,默认为 0.6,取值范围 [0.0, 1.0]
    fadeOutDuration: 0.3, // 粒子淡出持续时间,默认为 0.3,必须小于等于 particleLifetime
    particleSpeed: 1.0, // 粒子速度,默认为 1.0
    particleSize: const SnappableParticleSize.squareFromRelativeWidth(0.01), // 粒子大小,默认相对宽度的1%
  ),
);

颗粒大小属性详解

对于 particleSize 属性,有两种方式来定义粒子的尺寸:

  • 相对于组件大小:可以基于父级组件的宽高比例来设定粒子大小。

    SnappableParticleSize.relative(width: 0.01, height: 0.02) // 组件宽度的1%,高度的2%
    SnappableParticleSize.squareFromRelativeWidth(0.01) // 组件宽度的1%,保持正方形
    SnappableParticleSize.squareFromRelativeHeight(0.01) // 组件高度的1%,保持正方形
    
  • 绝对尺寸 (以dp为单位):直接指定粒子的具体尺寸。

    SnappableParticleSize.absoluteDp(width: 16, height: 8) // 16dp宽度,8dp高度
    

示例代码

下面是一个完整的示例代码,演示了如何结合 AnimationControllerSlider 来控制 Snappable 小部件的动画过程。

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

class AnimationControllerExampleScreen extends StatefulWidget {
  static const routeName = '/animation_controller_example_screen';

  const AnimationControllerExampleScreen({super.key});

  @override
  State<AnimationControllerExampleScreen> createState() => _AnimationControllerExampleScreenState();
}

class _AnimationControllerExampleScreenState extends State<AnimationControllerExampleScreen>
    with SingleTickerProviderStateMixin {
  late final _animationController = AnimationController(
    vsync: this,
    duration: const Duration(milliseconds: 1500),
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Animation Controller Example'),
      ),
      body: Column(
        children: [
          Spacer(),
          Snappable(
            animation: _animationController,
            outerPadding: const EdgeInsets.all(40),
            style: const SnappableStyle(
              particleSize: SnappableParticleSize.absoluteDp(
                width: 8,
                height: 8,
              ),
            ),
            child: Image.network('https://via.placeholder.com/150'), // 替换为您的图片URL
          ),
          Spacer(),
          Snappable(
            animation: _animationController,
            style: const SnappableStyle(
              particleSize: SnappableParticleSize.squareFromRelativeHeight(0.03),
            ),
            child: const FlutterLogo(
              size: 200,
              style: FlutterLogoStyle.stacked,
            ),
          ),
          Spacer(),
          Padding(
            padding: const EdgeInsets.all(32.0),
            child: AnimatedBuilder(
              animation: _animationController,
              builder: (BuildContext context, Widget? child) {
                return Slider(
                  value: _animationController.value,
                  onChanged: (value) => _animationController.value = value,
                );
              },
            ),
          ),
          Spacer(),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          _animationController.forward(from: 0);
        },
        tooltip: 'Start',
        child: const Icon(Icons.play_arrow),
      ),
    );
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }
}

在这个例子中,我们创建了一个包含两个 Snappable 小部件的页面,其中一个用于显示随机图片,另一个用于显示Flutter标志。同时,页面底部有一个滑块控件,用户可以通过拖动滑块来手动控制动画进度;还有一个浮动按钮,点击后会触发动画播放。


更多关于Flutter特效插件thanos_snap_effect的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter特效插件thanos_snap_effect的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用thanos_snap_effect插件的一个示例。这个插件允许你在Flutter应用中添加类似Snapchat的拍照效果。首先,你需要确保在你的pubspec.yaml文件中添加了该插件的依赖项:

dependencies:
  flutter:
    sdk: flutter
  thanos_snap_effect: ^最新版本号  # 请替换为实际最新版本号

然后,运行flutter pub get来安装依赖。

接下来,在你的Flutter项目中,你可以按照以下方式使用这个插件:

  1. 导入插件

    在你的Dart文件中(例如main.dart),首先导入插件:

    import 'package:thanos_snap_effect/thanos_snap_effect.dart';
    
  2. 创建SnapEffectController

    你需要一个SnapEffectController来控制拍照效果。这通常在你的State类中初始化:

    class _MyHomePageState extends State<MyHomePage> {
      late SnapEffectController snapEffectController;
    
      @override
      void initState() {
        super.initState();
        snapEffectController = SnapEffectController();
      }
    
      @override
      void dispose() {
        snapEffectController.dispose();
        super.dispose();
      }
    }
    
  3. 使用SnapEffectWidget

    在你的UI中,使用SnapEffectWidget来包裹你想要应用拍照效果的组件。例如,如果你有一个CameraPreview组件,你可以这样做:

    import 'package:camera/camera.dart';
    import 'package:flutter/material.dart';
    
    class MyHomePage extends StatefulWidget {
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      late CameraController cameraController;
      late SnapEffectController snapEffectController;
    
      @override
      void initState() {
        super.initState();
        cameraController = CameraController(CameraDescription(0, "后置摄像头"));
        cameraController.initialize().then((_) {
          if (!mounted) return;
          setState(() {});
        });
        snapEffectController = SnapEffectController();
      }
    
      @override
      void dispose() {
        cameraController.dispose();
        snapEffectController.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Snap Effect Demo'),
          ),
          body: cameraController.value.isInitialized
              ? Stack(
                  children: [
                    CameraPreview(cameraController),
                    Positioned.fill(
                      child: SnapEffectWidget(
                        controller: snapEffectController,
                        child: Material(
                          color: Colors.transparent,
                          child: GestureDetector(
                            onTap: () {
                              // 在这里处理拍照逻辑
                              print("拍照被触发");
    
                              // 可以触发Snap Effect
                              snapEffectController.triggerSnapEffect();
                            },
                          ),
                        ),
                      ),
                    ),
                  ],
                )
              : Center(child: CircularProgressIndicator()),
        );
      }
    }
    

在这个例子中,我们创建了一个包含CameraPreview的堆栈,并在其上叠加了一个SnapEffectWidget。当用户点击屏幕时,会触发拍照逻辑并调用snapEffectController.triggerSnapEffect()来显示Snapchat风格的拍照效果。

请注意,为了运行这个示例,你还需要添加camera插件的依赖,并请求相机权限。这个示例仅展示了如何使用thanos_snap_effect插件,实际项目中你可能需要更多的错误处理和逻辑来完善功能。

确保在实际应用中处理相机权限请求和错误处理,以提供良好的用户体验。

回到顶部