
import 'package:flutter/material.dart';
class ExplicitAnimationsScreen extends StatefulWidget {
const ExplicitAnimationsScreen({super.key});
State<ExplicitAnimationsScreen> createState() =>
_ExplicitAnimationsScreenState();
}
class _ExplicitAnimationsScreenState extends State<ExplicitAnimationsScreen>
with SingleTickerProviderStateMixin {
late final AnimationController _animationController = AnimationController(
vsync: this,
duration: const Duration(seconds: 2),
);
late final Animation<Decoration> _decoration = DecorationTween(
begin: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(20),
),
end: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(120),
),
).animate(_animationController);
late final Animation<double> _rotation = Tween(
begin: 0.0,
end: 2.0,
).animate(_animationController);
late final Animation<double> _scale = Tween(
begin: 1.0,
end: 1.1,
).animate(_animationController);
late final Animation<Offset> _position = Tween(
begin: Offset.zero,
end: const Offset(0, -0.2),
).animate(_animationController);
void _play() {
_animationController.forward();
}
void _pause() {
_animationController.stop();
}
void _rewind() {
_animationController.reverse();
}
void dispose() {
_animationController.dispose();
super.dispose();
}
Widget build(BuildContext context) {
print("build");
return Scaffold(
appBar: AppBar(
title: const Text('Explicit Animations'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SlideTransition(
position: _position,
child: ScaleTransition(
scale: _scale,
child: RotationTransition(
turns: _rotation,
child: DecoratedBoxTransition(
decoration: _decoration,
child: const SizedBox(
height: 400,
width: 400,
),
),
),
),
),
const SizedBox(
height: 50,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _play,
child: const Text("Play"),
),
ElevatedButton(
onPressed: _pause,
child: const Text("Pause"),
),
ElevatedButton(
onPressed: _rewind,
child: const Text("Rewind"),
)
],
)
],
),
),
);
}
}
이 Flutter 예제에서 사용된 다양한 애니메이션 객체와 애니메이션 위젯은 각각의 독특한 애니메이션 효과를 구현하고, 이들을 조합하여 복합적인 애니메이션 효과를 만듭니다. 아래에서 각 애니메이션 객체와 위젯의 역할과 작동 방식을 자세히 설명하겠습니다.
DecorationTween을 사용하여 박스의 BoxDecoration을 애니메이션화합니다.begin과 end로 시작 및 종료 상태를 정의합니다. 여기서는 색상(color)과 테두리 반경(borderRadius)이 변합니다.Colors.amber에서 Colors.red로, 테두리 반경은 20에서 120으로 부드럽게 변화합니다.Tween<double>을 사용하여 회전 애니메이션을 구현합니다.begin 값 0.0과 end 값 2.0은 회전을 나타내며, 이는 360도 회전을 두 번 수행함을 의미합니다._animationController의 진행 상태에 따라 위젯이 회전합니다.Tween<double>을 사용하여 크기 변화(scale) 애니메이션을 만듭니다.Tween<Offset>을 사용하여 위젯의 위치 이동 애니메이션을 만듭니다.Offset.zero에서 Offset(0, -0.2)로 이동하는 것은 위젯이 수직 방향으로 약간 위로 이동함을 의미합니다._position 애니메이션을 적용하여 위젯의 위치를 이동시킵니다.SlideTransition은 Offset 값을 사용하여 위젯의 위치를 변화시키는데, 이는 위젯을 수직 방향으로 부드럽게 이동시킵니다._scale 애니메이션을 적용하여 위젯의 크기를 조절합니다.ScaleTransition은 위젯의 크기를 확대하거나 축소하는 효과를 만듭니다._rotation 애니메이션을 적용하여 위젯을 회전시킵니다.RotationTransition은 위젯을 주어진 각도만큼 회전시키며, 이 경우에는 두 바퀴 회전합니다._decoration 애니메이션을 적용하여 위젯의 배경 색상과 테두리 반경을 변화시킵니다.DecoratedBoxTransition은 박스의 디자인을 변화시키며, 이는 색상과 테두리 반경의 부드러운 전환을 포함합니다.import 'package:flutter/material.dart';
class ExplicitAnimationsScreen extends StatefulWidget {
const ExplicitAnimationsScreen({super.key});
State<ExplicitAnimationsScreen> createState() =>
_ExplicitAnimationsScreenState();
}
class _ExplicitAnimationsScreenState extends State<ExplicitAnimationsScreen>
with SingleTickerProviderStateMixin {
late final AnimationController _animationController = AnimationController(
vsync: this,
duration: const Duration(seconds: 2),
reverseDuration: const Duration(seconds: 1),
);
late final Animation<Decoration> _decoration = DecorationTween(
begin: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(20),
),
end: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(120),
),
).animate(_curve);
late final Animation<double> _rotation = Tween(
begin: 0.0,
end: 0.5,
).animate(_curve);
late final Animation<double> _scale = Tween(
begin: 1.0,
end: 1.1,
).animate(_curve);
late final Animation<Offset> _position = Tween(
begin: Offset.zero,
end: const Offset(0, -0.2),
).animate(_curve);
late final CurvedAnimation _curve = CurvedAnimation(
parent: _animationController,
curve: Curves.elasticOut,
reverseCurve: Curves.bounceIn,
);
void _play() {
_animationController.forward();
}
void _pause() {
_animationController.stop();
}
void _rewind() {
_animationController.reverse();
}
void dispose() {
_animationController.dispose();
super.dispose();
}
Widget build(BuildContext context) {
print("build");
return Scaffold(
appBar: AppBar(
title: const Text('Explicit Animations'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SlideTransition(
position: _position,
child: ScaleTransition(
scale: _scale,
child: RotationTransition(
turns: _rotation,
child: DecoratedBoxTransition(
decoration: _decoration,
child: const SizedBox(
height: 400,
width: 400,
),
),
),
),
),
const SizedBox(
height: 50,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _play,
child: const Text("Play"),
),
ElevatedButton(
onPressed: _pause,
child: const Text("Pause"),
),
ElevatedButton(
onPressed: _rewind,
child: const Text("Rewind"),
)
],
)
],
),
),
);
}
}
이 코드의 CurvedAnimation 객체는 애니메이션에 특정한 가속도 곡선(curve)을 적용하여, 움직임의 자연스러움과 동적인 표현을 향상시키는 역할을 합니다. CurvedAnimation을 사용하면 애니메이션의 시작과 끝에서 속도를 조절하여 보다 부드러운 효과를 만들 수 있습니다.
parent:
parent 속성은 CurvedAnimation이 적용될 기본 Animation 객체를 지정합니다. 여기서는 _animationController가 parent로 사용되어, AnimationController에 곡선을 적용합니다.curve:
curve 속성은 애니메이션의 정방향 재생 시 적용될 가속도 곡선을 정의합니다.Curves.elasticOut는 애니메이션이 끝날 때 탄성 있는 효과를 줍니다. 이는 애니메이션이 목표 지점에 도달하면서 뒤로 조금 당겨진 후 최종 상태로 돌아오는 효과를 만들어냅니다.reverseCurve:
reverseCurve는 애니메이션이 역방향으로 재생될 때 적용될 가속도 곡선을 정의합니다.Curves.bounceIn은 애니메이션이 역방향으로 재생될 때 튕기는 듯한 효과를 줍니다. 이는 애니메이션이 시작 지점으로 돌아갈 때 마치 공이 튕기는 것처럼 동작합니다.CurvedAnimation은 애니메이션에 생동감을 더하기 위한 중요한 도구입니다. 기본적인 선형 또는 일정한 속도의 애니메이션 대신에, 이를 사용하면 다음과 같은 효과를 얻을 수 있습니다:
이러한 방식으로 CurvedAnimation은 Flutter 애플리케이션에서 애니메이션의 품질을 높이는 데 기여하며, 사용자에게 더욱 풍부하고 매력적인 인터랙션을 제공합니다.