Flutter关键帧动画插件keyframes_tween的使用

Flutter关键帧动画插件keyframes_tween的使用

keyframes_tween 是一个允许为各种属性定义关键帧的插件。通过使用 keyframes_tween,您可以创建复杂的动画效果,比如在不同时间点改变对象的大小、颜色或位置。

快速开始

以下是一个简单的示例,展示如何使用 keyframes_tween 创建一个动画:

import 'package:keyframes_tween/keyframes_tween.dart';

class Example extends StatefulWidget {
  @override
  _ExampleState createState() => _ExampleState();
}

class _ExampleState extends State<Example> with TickerProviderStateMixin {
  late final controller = AnimationController(
    duration: const Duration(seconds: 10),
    vsync: this,
  );

  final tween = KeyframesTween([
    KeyframeProperty<Size>(
      [
        Size(10, 10).keyframe(0), // 初始大小
        Size(100, 100).keyframe(0.5, Curves.easeInOut), // 中间大小
        Size(200, 200).keyframe(1.0), // 最终大小
      ],
    ),
    KeyframeProperty<Color>(
      [
        Colors.black.keyframe(0.0), // 初始颜色
        Colors.red.keyframe(0.8, Curves.easeInOut), // 中间颜色
        Colors.blue.keyframe(1.0), // 最终颜色
      ],
      name: 'background',
    ),
  ]);

  @override
  void initState() {
    controller.repeat(reverse: true); // 循环播放动画并反向播放
    super.initState();
  }

  @override
  void dispose() {
    controller.dispose(); // 释放资源
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder<KeyframeValue>(
      valueListenable: tween.animate(controller),
      builder: (context, values, _) => Container(
        width: values<Size>().width, // 获取当前大小宽度
        height: values<Size>().height, // 获取当前大小高度
        color: values<Color>('background'), // 获取当前背景颜色
      ),
    );
  }
}

在这个示例中,我们创建了一个 AnimationController 来控制动画的持续时间和触发方式。然后我们定义了一个 KeyframesTween 对象,它包含两个关键帧属性:一个是 Size 类型的大小变化,另一个是 Color 类型的颜色变化。我们使用 ValueListenableBuilder 来监听动画的变化,并更新 Container 的大小和背景颜色。

使用时长

除了直接指定关键帧的位置,还可以使用时长来定义关键帧的位置。以下是一个示例:

final tween = KeyframesTween.fromTime(
  properties: [
    TimeKeyframeProperty<Size>(
      [
        Size(10, 10).timeframe(milliseconds: 0), // 初始大小
        Size(100, 100).timeframe(milliseconds: 500, Curves.easeInOut), // 中间大小
        Size(200, 200).timeframe(seconds: 1), // 最终大小
      ],
    ),
    TimeKeyframeProperty<Color>(
      [
        Colors.black.timeframe(milliseconds: 0), // 初始颜色
        Colors.red.timeframe(milliseconds: 800, Curves.easeInOut), // 中间颜色
        Colors.blue.timeframe(seconds: 1), // 最终颜色
      ],
      name: 'background',
    ),
  ],
);

在这个示例中,我们使用了 fromTime 方法来定义关键帧的位置,以时长(毫秒或秒)为单位。

自定义插值器

如果您希望自定义属性之间的插值方式,可以使用 lerp 方法:

final tween = KeyframesTween(
  properties: [
    KeyframeProperty<MyType>(
      [
        // 自定义插值
      ],
      lerp: (begin, end, t) => MyType.lerp(begin, end, t),
    )
  ],
);

在这个示例中,lerp 方法用于自定义从 beginend 的插值计算。

构建器

最后,我们需要使用 ValueListenableBuilder 来构建动画效果:

return ValueListenableBuilder<KeyframeValue>(
  valueListenable: tween.animate(controller),
  builder: (context, values, _) => Container(
    width: values<Size>().width,
    height: values<Size>().height,
    color: values<Color>('background'),
  ),
);

更多关于Flutter关键帧动画插件keyframes_tween的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

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


当然,下面是一个关于如何在Flutter中使用keyframes_tween插件进行关键帧动画的示例代码。keyframes_tween允许你定义多个关键帧,从而在动画过程中实现更复杂的变化。

首先,确保你已经在pubspec.yaml文件中添加了keyframes_tween依赖:

dependencies:
  flutter:
    sdk: flutter
  keyframes_tween: ^x.y.z  # 请替换为最新版本号

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

以下是一个完整的示例代码,展示如何使用keyframes_tween在Flutter中实现一个颜色渐变的关键帧动画:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Keyframes Tween Animation'),
        ),
        body: Center(
          child: AnimatedBuilder<Color>(
            animation: _keyframesTweenAnimationController,
            builder: (context, color, child) {
              return Container(
                width: 200,
                height: 200,
                color: color,
              );
            },
            child: null,
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            _keyframesTweenAnimationController.repeat();
          },
          tooltip: 'Start Animation',
          child: Icon(Icons.play_arrow),
        ),
      ),
    );
  }
}

final List<Keyframe<Color>> _keyframes = [
  Keyframe<Color>(
    time: 0.0,
    value: Colors.red,
  ),
  Keyframe<Color>(
    time: 0.5,
    value: Colors.yellow,
  ),
  Keyframe<Color>(
    time: 1.0,
    value: Colors.green,
  ),
];

final KeyframesTween<Color> _keyframesTween = KeyframesTween<Color>(keyframes: _keyframes);
AnimationController _keyframesTweenAnimationController;

@override
void initState() {
  super.initState();
  _keyframesTweenAnimationController = AnimationController(
    duration: const Duration(seconds: 2),
    vsync: const TickerProviderStateMixin(),
  )..repeat(reverse: true);

  _keyframesTweenAnimationController.value = _keyframesTween.transform(_keyframesTweenAnimationController);
}

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

解释

  1. 依赖引入: 在pubspec.yaml中添加keyframes_tween依赖,然后运行flutter pub get

  2. 关键帧定义: 使用Keyframe<Color>定义了一组关键帧,每个关键帧指定了一个时间和颜色值。

  3. KeyframesTween: 使用KeyframesTween<Color>来创建一个关键帧动画,并传入之前定义的关键帧列表。

  4. AnimationController: 创建一个AnimationController来控制动画的时长和速率。

  5. AnimatedBuilder: 使用AnimatedBuilder来监听动画值的变化,并根据动画值更新UI。在这里,我们根据动画值更新一个Container的颜色。

  6. FloatingActionButton: 添加一个浮动按钮,当点击按钮时,动画会重新开始。

注意:在上面的代码中,我们试图直接将_keyframesTween.transform(_keyframesTweenAnimationController)赋值给_keyframesTweenAnimationController.value,但这是不正确的做法,因为AnimationController的值是由其自身管理的。为了正确应用关键帧动画,我们需要一个Animation<Color>来桥接AnimationControllerKeyframesTween。下面是修正后的代码段:

final Animation<Color> _colorAnimation = _keyframesTween.animate(_keyframesTweenAnimationController);

并在AnimatedBuilder中使用_colorAnimation作为动画值:

AnimatedBuilder<Color>(
  animation: _colorAnimation,
  // ...其余代码保持不变
)

确保在initState方法中正确初始化这个动画:

@override
void initState() {
  super.initState();
  _keyframesTweenAnimationController = AnimationController(
    duration: const Duration(seconds: 2),
    vsync: const TickerProviderStateMixin(),
  )..repeat(reverse: true);
}

这样,你的关键帧动画应该能够正确运行了。

回到顶部