나와 팀원 그리고 디자이너는 올해, 더 성장하기 위해서 플러터로 구현할 수 있는
애니메이션을 연습해 보고, 우리 앱에 적용시켜 보기로 했다.
쉬운 것부터 하나씩, 서로 구현해 보고 싶은 애니메이션을 하기로 했다.
그 첫 번째로 아래와 같은 애니메이션이다.
먼저, 디자이너가 피그마로 이 애니메이션을 만들어 주었다.
나는 피그마를 참고해서 Curve 값이나, 속도 등을 그대로 적용시키기로 했다.
처음 만들 때, 값을 제대로 확인하지 않고 '이거, 같은 속도로 커지고 있다'고 생각해서
플러터에서 기본적으로 제공해 주는 Curves.linear
를 적용시켜보았다.
하지만...
커지는 느낌이 너무 많이 달랐다.
그래서 값을 제대로 봐야겠다 싶어 피그마 값을 확인했다.
커지는 애니메이션에는 가속도가 있었다...
그렇다면, 내가 원하는 대로 커브 값을 줄 수 있을까?
물론 가능하다.
Curves의 구조를 보면 Cubic
으로 직접 값을 줘서 구현한 것을 알 수 있는데
그렇다면 우리도 직접 값을 주면 점점 가속되거나 감속시킬 수 있지 않을까?
const Cubic(a,b,c,d);
// a와 b: 곡선의 시작 제어점(x1, y1)
// c와 d: 곡선의 끝 제어점(x2, y2)
// 0 <= x <= 1 범위의 값만 줘야함.
Stiffness
Damping
Mass
값을 어떤 식으로 계산해서 넣어야 하는지는
어려워서 채찍피티와 함께 했다.
그래서 구해준 값은...
const Cubic(0.23, 0.86, 0.29, 1)
이 값을 적용시켜 주니
그 다음은 작아지면서 약간 통통 튀는 듯한 애니메이션을 줘야 한다.
즉, 애니메이션이 두 개가 연속으로 보여진다는 것이다.
어떻게 애니메이션을 연속으로 보여줄까 생각하다가
AnimationController
에는 리스너를 추가할 수 있었고
AnimaitionStatus
라는 enum도 있었다.
1번 애니메이션이 끝난다면, 2번 애니메이션을 진행시키자! 라는 생각이 들었다.
extendController.addStatusListener((status) async {
if (status == AnimationStatus.completed) {
await Future.delayed(const Duration(milliseconds: 200));
bounceController.forward();
}
});
위와 같이 작성했다.
200ms 딜레이를 넣은 이유는 첫 번째 애니메이션과 두 번째 애니메이션에 딜레이가 있다고 느꼈기 때문.
그리고, 애니메이션을 한 번만 재생시킬 게 아니기 때문에
두 번째 애니메이션이 끝나면 초기 상태로 되돌려 놓아야 했다.
bounceController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
extendController.reset();
bounceController.reset();
}
});
이런 식으로.
flutter에서는 여러 Curves를 제공해 주는데 그 중에서 당연히 튀기는 듯한 느낌은 bounceOut
이 있다.
바로 적용시켜 보았는데...
음... 뭔가 강도가 약한 듯한 느낌이 들었다.
속도를 줄이면 너무 빨리 끝나서 튀기는 듯한 느낌이 들지 않았고
크기를 키우거나 줄이기에는 피그마의 애니메이션과 느낌이 매우 달랐다.
그렇다면 이것은 Curve를 커스텀해야 되겠다고 생각했다...
class CustomBounceCurve extends Curve {
double transform(double t) {
const double amplitude = 0.5;
const double period = 0.4;
if (t == 0.0) return 0.0;
if (t == 1.0) return 1.0;
return 1.0 -
amplitude *
pow(2.0, -10.0 * t) *
sin((t - period / 4.0) * (2 * pi) / period);
}
}
위 코드인데, 어떻게 구현해야 될지 몰라서
이것도 채찍피티와 함께 했다.
나중에는 함께 하지 않고도 구현할 수 있으면 좋겠다...
아무튼 이 Custon Curve를 적용시키고 보니
정말 간단한 애니메이션인데도 많이 복잡했다.
그래도 이것저것 찾아보면서 재미는 있었다.
아직 복잡한 애니메이션을 구현할 실력은 없지만,
계속 하다 보면 언젠가 구현하게 될 수 있지 않을까...
GG
이것저것 찾아보다가 좋은 라이브러리를 발견했다.
바로 Sprung
이라는 라이브러리이다.
Spring animation
을 구현해주는 라이브러리인데
피그마에서 mass, stiffness, damping 값을 넘겨주면 알아서 적절한 커브를 만들어준다...!
extendAnimation = Tween<double>(begin: start, end: end).animate(
CurvedAnimation(
parent: extendController,
curve: Sprung.custom(
mass: 1,
stiffness: 250,
damping: 31.6,
),
),
);