※これは2024年6月に書いています
Flutterで下の図のようなオブジェクトをアニメーションをさせたかったのですが、Animationが今一つ理解できなかったので、AIにサンプルを生成させてみることにしました。
※Geminiはadvanceではない方。ChatGPTは無料のもの。
指示文
二つのウィジットA、Bがあり、A、Bを格納するウィジットCがあります
これらはすべて同時にアニメーションします
Cは前後運動と同時に回転運動をします
Aは三つの画像X、Y、Zを順番に表示します
Bは回転運動をします
Flutterのコードで生成してください
結果
こんな微妙な指示文で出力してくれるのにまず驚きました。
Geminiは三案ほど出力してくれたのですが、3案とも意図したものと少し違うようでした。
無料版ではChatGPTの方が使えそうな雰囲気です。
すごい時代になりました。
Geminiの出力(A案のみ記載)
import 'package:flutter/material.dart';
class AnimatedContainerExample extends StatefulWidget {
@override
_AnimatedContainerExampleState createState() =>
_AnimatedContainerExampleState();
}
class _AnimatedContainerExampleState extends State
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _animationFrontToBack;
Animation _animationBackToFront;
Animation _rotationAnimation;
Animation _imageIndexAnimation;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 4),
)..repeat();
_animationFrontToBack = Tween(begin: 0.0, end: 1.0)
.animate(_controller);
_animationBackToFront = Tween(begin: 1.0, end: 0.0)
.animate(_controller);
_rotationAnimation = Tween(begin: 0.0, end: 360.0)
.animate(_controller);
_imageIndexAnimation = Tween(begin: 0, end: 2)
.animate(_controller.repeatDuration);
_controller.addListener(() {
setState(() {});
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedContainer(
duration: const Duration(seconds: 2),
curve: Curves.easeInOut,
transform: Matrix4.identity()
..translate(
0.0,
_animationFrontToBack.value * 100 -
_animationBackToFront.value * 100),
child: AnimatedRotation(
turns: _rotationAnimation.value / 360,
duration: const Duration(seconds: 2),
curve: Curves.easeInOut,
child: Container(
width: 200,
height: 200,
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 500),
transition: ScaleTransition(scale: 2),
child: IndexedStack(
index: _imageIndexAnimation.value,
children: [
Image.asset('assets/image_x.png'),
Image.asset('assets/image_y.png'),
Image.asset('assets/image_z.png'),
],
),
),
),
),
),
const SizedBox(height: 20),
Text('Widget C'),
],
),
);
}
}
ChatGPTの出力
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: WidgetC(),
),
),
);
}
}
class WidgetC extends StatefulWidget {
@override
_WidgetCState createState() => _WidgetCState();
}
class _WidgetCState extends State with TickerProviderStateMixin {
late AnimationController _controller;
late Animation _slideAnimation;
late Animation _rotationAnimation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: Duration(seconds: 3),
vsync: this,
)..repeat(reverse: true);
_slideAnimation = Tween(
begin: Offset(-0.1, 0),
end: Offset(0.1, 0),
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut,
));
_rotationAnimation = Tween(
begin: 0,
end: 2 * 3.141592653589793,
).animate(_controller);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SlideTransition(
position: _slideAnimation,
child: RotationTransition(
turns: _rotationAnimation,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
WidgetA(),
SizedBox(height: 20),
WidgetB(),
],
),
),
);
}
}
class WidgetA extends StatefulWidget {
@override
_WidgetAState createState() => _WidgetAState();
}
class _WidgetAState extends State with TickerProviderStateMixin {
late AnimationController _controller;
late List images;
int currentIndex = 0;
@override
void initState() {
super.initState();
images = ['assets/image_x.png', 'assets/image_y.png', 'assets/image_z.png'];
_controller = AnimationController(
duration: Duration(seconds: 1),
vsync: this,
)..repeat();
_controller.addListener(() {
setState(() {
currentIndex = (_controller.value * images.length).floor() % images.length;
});
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Image.asset(images[currentIndex]);
}
}
class WidgetB extends StatefulWidget {
@override
_WidgetBState createState() => _WidgetBState();
}
class _WidgetBState extends State with TickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: Duration(seconds: 3),
vsync: this,
)..repeat();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return RotationTransition(
turns: _controller,
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
);
}
}