Flutter基于弹簧的动画和模拟插件springster的使用

发布于 1周前 作者 vueper 最后一次编辑是 5天前 来自 Flutter

Flutter基于弹簧的动画和模拟插件springster的使用

Springster

Pub Version Coverage lintervention_badge Bluesky

Springster简化了基于弹簧的动画和模拟。

Features 🎯

  • 🎨 带有可定制弹跳和持续时间的简单基于弹簧的动画
  • 🔄 基于弹簧的可拖动小部件,带有平滑返回动画
  • 💯 可用于标准Flutter动画的弹簧曲线
  • 📱 复杂运动的二维弹簧动画

Try it out

Open Example

Installation 💻

❗要开始使用Springster,您必须在您的机器上安装Dart SDK

将以下内容添加到您的pubspec.yaml文件中:

dependencies:
  springster: ^latest_version

或者通过dart pub命令安装:

dart pub add springster

Usage 💡

Simple Spring Animation

使用SpringBuilder进行基本的弹簧动画:

1D Hover example gif

SpringBuilder(
  spring: SimpleSpring.bouncy,
  value: targetValue, // Changes trigger smooth spring animation
  builder: (context, value, child) {
    return Container(
      width: value,
      height: value,
      color: Colors.blue,
    );
  },
)

如果您想要简单的二维弹簧动画,可以使用SpringBuilder2D

2D Redirection example gif

SpringBuilder2D(
  spring: SimpleSpring.bouncy,
  value: (100, 100), // Changes trigger smooth spring animation and redirect dynamically
  builder: (context, value, child) {
    return Transform.translate(
      offset: Offset(value.x, value.y),
      child: child,
    );
  },
  child: Container(
    width: 100,
    height: 100,
    color: Colors.blue,
  ),
)

Spring Draggable

springster提供了一个SpringDraggable小部件,允许您在屏幕上拖动小部件,并带有弹簧返回动画。它的工作方式与Flutter中的Draggable小部件类似,并支持原生Flutter DragTarget,但具有一些合理的默认设置和额外功能。

Spring Draggable example gif

SpringDraggable(
  spring: SimpleSpring.bouncy,
  child: Container(
    width: 100,
    height: 100,
    color: Colors.blue,
  ),
  data: 'my-draggable-data',
)

Low-level Spring Simulation

如果您需要对弹簧模拟有更多的控制,您可以使用SpringSimulationControllerSpringSimulationController2D类。

final controller = SpringSimulationController(
  spring: SimpleSpring.bouncy,
  vsync: this,
);

它们类似于Flutter中的AnimationController类,允许您通过目标值驱动弹簧模拟,同时在目标变化之间保持速度。

Predefined Springs 🎯

Springster提供了几种预定义的弹簧配置:

  • const SimpleSpring() - 平滑无弹跳的弹簧
  • SimpleSpring.instant - 几乎即时的弹簧
  • SimpleSpring.defaultIOS - 类似iOS风格的平滑无弹跳弹簧
  • SimpleSpring.bouncy - 弹跳较高的弹簧
  • SimpleSpring.snappy - 小弹跳的快速弹簧
  • SimpleSpring.interactive - 交互式动画的低响应弹簧

您还可以创建自定义弹簧:

const mySpring = SimpleSpring(
  duration: 0.5, // 定位持续时间
  bounce: 0.2,   // 弹跳量(-1到1)
);

// 或者使用阻尼分数
const mySpring = SimpleSpring.withDamping(
  dampingFraction: 0.7,
  duration: 0.5,
);

Acknowledgements

Springster部分改编并深受fluid_animations的启发。

示例代码

以下是springster的一个完整示例demo,展示了如何在应用程序中使用springster的不同功能。

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

void main() {
  runApp(SpringsterExampleApp());
}

class SpringsterExampleApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Springster Examples',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: SpringsterExample(),
    );
  }
}

class SpringsterExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Springster Examples'),
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          _buildExampleButton(context, 'One Dimension', OneDimensionExample()),
          SizedBox(height: 16),
          _buildExampleButton(context, 'Two Dimension Redirection', TwoDimensionRedirectionExample()),
          SizedBox(height: 16),
          _buildExampleButton(context, 'Draggable Icons', DraggableIconsExample()),
          SizedBox(height: 16),
          _buildExampleButton(context, 'Picture in Picture', PipExample()),
          SizedBox(height: 16),
          _buildExampleButton(context, 'Flip Card', FlipCardExample()),
        ],
      ),
    );
  }

  Widget _buildExampleButton(BuildContext context, String label, Widget page) {
    return ElevatedButton(
      onPressed: () {
        Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => page),
        );
      },
      child: Text(label),
    );
  }
}

class OneDimensionExample extends StatefulWidget {
  @override
  _OneDimensionExampleState createState() => _OneDimensionExampleState();
}

class _OneDimensionExampleState extends State<OneDimensionExample> with SingleTickerProviderStateMixin {
  double _value = 100;

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('One Dimension')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            SpringBuilder(
              spring: SimpleSpring.bouncy,
              value: _value,
              builder: (context, value, child) {
                return Container(
                  width: value,
                  height: value,
                  color: Colors.blue,
                );
              },
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  _value = _value == 100 ? 200 : 100;
                });
              },
              child: Text('Toggle Size'),
            ),
          ],
        ),
      ),
    );
  }
}

class TwoDimensionRedirectionExample extends StatefulWidget {
  @override
  _TwoDimensionRedirectionExampleState createState() => _TwoDimensionRedirectionExampleState();
}

class _TwoDimensionRedirectionExampleState extends State<TwoDimensionRedirectionExample> with SingleTickerProviderStateMixin {
  Offset _offset = Offset(100, 100);

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Two Dimension Redirection')),
      body: GestureDetector(
        onPanUpdate: (details) {
          setState(() {
            _offset += Offset(details.delta.dx, details.delta.dy);
          });
        },
        child: SpringBuilder2D(
          spring: SimpleSpring.bouncy,
          value: _offset,
          builder: (context, value, child) {
            return Transform.translate(
              offset: Offset(value.x, value.y),
              child: Container(
                width: 100,
                height: 100,
                color: Colors.blue,
              ),
            );
          },
        ),
      ),
    );
  }
}

class DraggableIconsExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Draggable Icons')),
      body: Center(
        child: SpringDraggable(
          spring: SimpleSpring.bouncy,
          child: Container(
            width: 100,
            height: 100,
            color: Colors.blue,
          ),
          data: 'my-draggable-data',
        ),
      ),
    );
  }
}

class PipExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Picture in Picture')),
      body: Center(
        child: Text('Pip Example Content'),
      ),
    );
  }
}

class FlipCardExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Flip Card')),
      body: Center(
        child: Text('Flip Card Example Content'),
      ),
    );
  }
}

这个完整的示例代码演示了如何使用springster插件的各种功能,包括一维和二维弹簧动画、可拖动的小部件等。希望这对您有所帮助!


更多关于Flutter基于弹簧的动画和模拟插件springster的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter基于弹簧的动画和模拟插件springster的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在探索和使用Flutter中的未知功能插件,如springster时,了解其API和功能是实现高效开发的关键。虽然springster可能不是一个广为人知的Flutter插件,但探索其使用通常涉及查看官方文档、示例代码和进行实际测试。由于我无法直接访问实时的插件代码或文档(特别是如果它是一个非官方或小众插件),我将提供一个假设性的代码案例,展示如何集成和使用一个假设的Flutter插件。

假设的springster插件功能

假设springster插件提供了一些与动画或UI效果相关的功能,例如创建弹簧动画效果。以下是一个基于这种假设的代码案例:

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加springster插件的依赖(注意:这里假设的依赖名和版本号是虚构的):

dependencies:
  flutter:
    sdk: flutter
  springster: ^1.0.0  # 假设的版本号

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

2. 导入插件

在你的Dart文件中导入springster插件:

import 'package:springster/springster.dart';

3. 使用插件功能

假设springster插件提供了一个SpringAnimation小部件,用于创建弹簧动画效果。以下是一个示例代码,展示如何使用这个小部件:

import 'package:flutter/material.dart';
import 'package:springster/springster.dart'; // 导入插件

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Springster Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 2),
      vsync: this,
    )..repeat(reverse: true); // 假设动画会反复播放
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Springster Demo'),
      ),
      body: Center(
        child: SpringAnimationWidget( // 假设的小部件
          animation: _controller,
          child: Container(
            width: 100,
            height: 100,
            color: Colors.red,
          ),
          // 假设的弹簧动画配置参数
          springConfig: SpringConfig(
            stiffness: 0.5, // 弹簧刚度
            dampingRatio: 0.2, // 阻尼比
          ),
        ),
      ),
    );
  }
}

// 假设的SpringAnimationWidget小部件定义(注意:这不是真实代码,仅作为示例)
class SpringAnimationWidget extends AnimatedWidget {
  final Animation<double> animation;
  final Widget child;
  final SpringConfig springConfig;

  SpringAnimationWidget({
    Key? key,
    required this.animation,
    required this.child,
    required this.springConfig,
  }) : super(key: key, listenable: animation);

  @override
  Widget build(BuildContext context) {
    // 这里应该使用springConfig和animation来计算实际的位置或变换
    // 但由于这是假设的代码,我们仅返回child并应用一个简单的变换作为示例
    final transform = Matrix4.identity()
      ..translate(animation.value * 100.0, 0.0, 0.0); // 假设的平移变换

    return Transform(
      transform: transform,
      child: child,
    );
  }
}

// 假设的SpringConfig类定义(同样,这不是真实代码)
class SpringConfig {
  final double stiffness;
  final double dampingRatio;

  SpringConfig({required this.stiffness, required this.dampingRatio});
}

注意

  • 上面的代码是一个假设性的示例,用于说明如何集成和使用一个假设的Flutter插件。
  • SpringAnimationWidgetSpringConfig类是基于假设创建的,实际插件可能有不同的API和用法。
  • 在实际开发中,你应该查阅springster插件的官方文档和示例代码,以了解如何正确使用其提供的功能。
  • 如果springster插件不存在或没有提供足够的文档,你可能需要寻找替代方案或自己实现所需的功能。
回到顶部