Reputation: 476
I am creating a n UNO game app and this is the intro screen part. I need a very custom kind of animation and I dont have much knowledge in flutter custom animations.
Here is a little preview
Now I want to create a "cards flying around" animation. It is basically cards (which are containers with svg assets) being translated and rotated AT THE SAME TIME across the screen to create a flying card effect. This animation will be repeated over and over.
I have managed to make a very basic version which just translates , doesnt rotate and doesnt look all that pretty. Here is the code.
INTROSCREEN
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',
),
);
}
}
Here is what I managed to build
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)),
),
),
);
}
}
In the above picture , the card is actually translating across the device's width back and forth.
I feel what I have created is the cumbersome way of doing animations. If anyone still didnt get what I mean by flying cards animation, the same kind of effect appears on angry birds game screen, it's just bird and pigs flying around. I need the same but with my cards.
Please check out this video and jump to 0:22 for a small reference of what UI I am hoping for.
I tried to reduce the complexity as much as I could. Thanks for your time!
Upvotes: 5
Views: 9784
Reputation: 476
I am also posting another way for doing this same task, which will be easier for a lot of people. However I will not mark this as the accepted answer because previous answer is the real way to do it.
firstly we need to add flare dependency. Flare is like lottie for flutter. Basically it helps us play pre-made vector animations in 60fps or more
dependencies:
flutter:
flare_flutter: ^2.0.3
now head over to 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
Once that is done, just export the animation in a binary format. the file will have .flr format.
now apply the animation from the assets folder.
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',
),
);
I hope it was useful in some way. I found it worth mentioning.
Upvotes: 1
Reputation: 2377
Here is a simple example that you can extend. The "Hello world!" text is translating and rotating.
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),
),
),
]));
}
}
Upvotes: 4