如何在 flutter 中应用平移和旋转动画来创建 "cards being flung around" 效果
How to apply translate and rotate animation in flutter to create a "cards being flung around" effect
我正在创建一个 UNO 游戏应用程序,这是介绍屏幕部分。我需要一种非常自定义的动画,而且我对 flutter 自定义动画知之甚少。
这是一个小预览
现在我想创建一个 "cards flying around" 动画。它基本上是卡片(它们是带有 svg 资产的容器)在屏幕上同时平移和旋转以创建飞行卡片效果。这个动画会一遍又一遍地重复。
我已经设法制作了一个非常基本的版本,它只是平移,不会旋转并且看起来并不那么漂亮。这是代码。
简介
class IntroScreen extends StatefulWidget {
@override
_IntroScreenState createState() => _IntroScreenState();
}
class _IntroScreenState extends State<IntroScreen>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
@override
void initState() {
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 4));
_animation = RainbowColorTween([
CardColors.COLOR1,
CardColors.COLOR2,
CardColors.COLOR3,
CardColors.COLOR4,
CardColors.COLOR1,
]).chain(CurveTween(curve: Curves.easeInOut)).animate(_controller);
_controller.addListener(() {
setState(() {});
});
_controller.repeat();
super.initState();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Container(
color: _animation.value,
child: ChangeNotifierProvider<_DataModel>(
create: (context) => _DataModel(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
SizedBox(
height: 100,
),
_Logo(),
SizedBox(
height: 50,
),
_TextField(),
_SelectCards(),
_Play(),
Expanded(child: FlyingCards(MediaQuery.of(context).size.width)),
],
),
),
),
),
);
}
}
class _Logo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SizedBox(
height: 200,
child: FlareActor(
"assets/intro_anim.flr",
alignment: Alignment.center,
fit: BoxFit.contain,
animation: 'intro',
),
);
}
}
这是我设法构建的
class FlyingCards extends StatefulWidget {
final double width;
FlyingCards(this.width);
@override
_FlyingCardsState createState() => _FlyingCardsState();
}
class _FlyingCardsState extends State<FlyingCards>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
@override
void initState() {
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 2));
_animation = Tween<double>(begin: 0, end: widget.width)
.chain(CurveTween(curve: Curves.ease))
.animate(_controller)
..addListener(() {
setState(() {});
})
..addStatusListener((status) {
if (status == AnimationStatus.dismissed)
_controller.forward();
else if (status == AnimationStatus.completed) _controller.reverse();
});
_controller.forward();
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Transform.translate(
offset: Offset(_animation.value, 0),
child: Container(
height: 50,
width: 50,
child: SvgPicture.asset('assets/plus4.svg'),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(20)),
),
),
);
}
}
在上图中,卡片实际上是在设备的宽度上来回移动。
感觉自己创作出来的动画制作方式比较繁琐。如果还有人不明白我说的飞卡动画是什么意思,愤怒的小鸟游戏画面上也会出现同样的效果,就是小鸟和猪飞来飞去。我需要同样的东西,但要用我的卡片。
请查看 this video 并跳转到 0:22 以获得 UI 我希望得到的小参考。
我尽可能地降低了复杂性。感谢您的宝贵时间!
这是一个您可以扩展的简单示例。
"Hello world!" 文本正在平移和旋转。
import 'package:flutter/material.dart';
import 'dart:math';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyAnim(),
),
),
);
}
}
class MyAnim extends StatefulWidget {
@override
State<MyAnim> createState() => MyAnimState();
}
class MyAnimState extends State<MyAnim> with SingleTickerProviderStateMixin {
AnimationController control;
Animation<double> rot;
Animation<double> trasl;
@override
void initState() {
super.initState();
control = AnimationController(
duration: Duration(seconds: 5),
vsync: this,
);
rot = Tween<double>(
begin: 0,
end: 2 * pi,
).animate(control);
trasl = Tween<double>(
begin: 0,
end: 300,
).animate(control);
control.repeat();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: control,
builder: (_, child) => Stack(children: <Widget>[
Positioned(
top: 100,
left: trasl.value,
child: Transform(
transform: Matrix4.rotationZ(rot.value),
alignment: Alignment.center,
child: Text('Hello, World!',
style: Theme.of(context).textTheme.headline4),
),
),
]));
}
}
我还发布了另一种方法来完成同样的任务,这对很多人来说会更容易。但是我不会将此标记为已接受的答案,因为以前的答案是真正的方法。
首先我们需要添加flare依赖。 Flare 就像 flutter 的 lottie。基本上它可以帮助我们以 60fps 或更高的速度播放预制矢量动画
dependencies:
flutter:
flare_flutter: ^2.0.3
现在前往 rive and create any animation that you like. You can add vectors and your own resources and create animations. I just made some cards using illustrator. you can see my cards flying animation here
完成后,只需以二进制格式导出动画即可。该文件将具有 .flr 格式。
现在应用资产文件夹中的动画。
import 'package:flare_flutter/flare_actor.dart';
return Container(
height: 200,
width: MediaQuery.of(context).size.width,
child: FlareActor(
"assets/cards_flying.flr",
alignment: Alignment.center,
fit: BoxFit.fill,
animation: 'cards',
),
);
我希望它在某些方面有用。我觉得值得一提。
我正在创建一个 UNO 游戏应用程序,这是介绍屏幕部分。我需要一种非常自定义的动画,而且我对 flutter 自定义动画知之甚少。
这是一个小预览
现在我想创建一个 "cards flying around" 动画。它基本上是卡片(它们是带有 svg 资产的容器)在屏幕上同时平移和旋转以创建飞行卡片效果。这个动画会一遍又一遍地重复。
我已经设法制作了一个非常基本的版本,它只是平移,不会旋转并且看起来并不那么漂亮。这是代码。
简介
class IntroScreen extends StatefulWidget {
@override
_IntroScreenState createState() => _IntroScreenState();
}
class _IntroScreenState extends State<IntroScreen>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
@override
void initState() {
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 4));
_animation = RainbowColorTween([
CardColors.COLOR1,
CardColors.COLOR2,
CardColors.COLOR3,
CardColors.COLOR4,
CardColors.COLOR1,
]).chain(CurveTween(curve: Curves.easeInOut)).animate(_controller);
_controller.addListener(() {
setState(() {});
});
_controller.repeat();
super.initState();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Container(
color: _animation.value,
child: ChangeNotifierProvider<_DataModel>(
create: (context) => _DataModel(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
SizedBox(
height: 100,
),
_Logo(),
SizedBox(
height: 50,
),
_TextField(),
_SelectCards(),
_Play(),
Expanded(child: FlyingCards(MediaQuery.of(context).size.width)),
],
),
),
),
),
);
}
}
class _Logo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SizedBox(
height: 200,
child: FlareActor(
"assets/intro_anim.flr",
alignment: Alignment.center,
fit: BoxFit.contain,
animation: 'intro',
),
);
}
}
这是我设法构建的
class FlyingCards extends StatefulWidget {
final double width;
FlyingCards(this.width);
@override
_FlyingCardsState createState() => _FlyingCardsState();
}
class _FlyingCardsState extends State<FlyingCards>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
@override
void initState() {
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 2));
_animation = Tween<double>(begin: 0, end: widget.width)
.chain(CurveTween(curve: Curves.ease))
.animate(_controller)
..addListener(() {
setState(() {});
})
..addStatusListener((status) {
if (status == AnimationStatus.dismissed)
_controller.forward();
else if (status == AnimationStatus.completed) _controller.reverse();
});
_controller.forward();
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Transform.translate(
offset: Offset(_animation.value, 0),
child: Container(
height: 50,
width: 50,
child: SvgPicture.asset('assets/plus4.svg'),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(20)),
),
),
);
}
}
在上图中,卡片实际上是在设备的宽度上来回移动。
感觉自己创作出来的动画制作方式比较繁琐。如果还有人不明白我说的飞卡动画是什么意思,愤怒的小鸟游戏画面上也会出现同样的效果,就是小鸟和猪飞来飞去。我需要同样的东西,但要用我的卡片。
请查看 this video 并跳转到 0:22 以获得 UI 我希望得到的小参考。
我尽可能地降低了复杂性。感谢您的宝贵时间!
这是一个您可以扩展的简单示例。 "Hello world!" 文本正在平移和旋转。
import 'package:flutter/material.dart';
import 'dart:math';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyAnim(),
),
),
);
}
}
class MyAnim extends StatefulWidget {
@override
State<MyAnim> createState() => MyAnimState();
}
class MyAnimState extends State<MyAnim> with SingleTickerProviderStateMixin {
AnimationController control;
Animation<double> rot;
Animation<double> trasl;
@override
void initState() {
super.initState();
control = AnimationController(
duration: Duration(seconds: 5),
vsync: this,
);
rot = Tween<double>(
begin: 0,
end: 2 * pi,
).animate(control);
trasl = Tween<double>(
begin: 0,
end: 300,
).animate(control);
control.repeat();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: control,
builder: (_, child) => Stack(children: <Widget>[
Positioned(
top: 100,
left: trasl.value,
child: Transform(
transform: Matrix4.rotationZ(rot.value),
alignment: Alignment.center,
child: Text('Hello, World!',
style: Theme.of(context).textTheme.headline4),
),
),
]));
}
}
我还发布了另一种方法来完成同样的任务,这对很多人来说会更容易。但是我不会将此标记为已接受的答案,因为以前的答案是真正的方法。
首先我们需要添加flare依赖。 Flare 就像 flutter 的 lottie。基本上它可以帮助我们以 60fps 或更高的速度播放预制矢量动画
dependencies:
flutter:
flare_flutter: ^2.0.3
现在前往 rive and create any animation that you like. You can add vectors and your own resources and create animations. I just made some cards using illustrator. you can see my cards flying animation here
完成后,只需以二进制格式导出动画即可。该文件将具有 .flr 格式。
现在应用资产文件夹中的动画。
import 'package:flare_flutter/flare_actor.dart';
return Container(
height: 200,
width: MediaQuery.of(context).size.width,
child: FlareActor(
"assets/cards_flying.flr",
alignment: Alignment.center,
fit: BoxFit.fill,
animation: 'cards',
),
);
我希望它在某些方面有用。我觉得值得一提。