[Flutter] 애니메이션 구현하기-①바운스

겨레·2025년 2월 10일
0
post-thumbnail

역량 강화를 위해 팀원과 디자이너와 함께 진행한 첫 애니메이션 효과는 통통 튀는 바운스 애니메이션!(전체 코드 확인은 깃허브에서 확인 가능~)

위에 gif가 내가 만든 애니메이션! (뿌듯...🧡)


✔ 디자인

디자이너가 피그마에 올려준 디자인과 인터렉션 효과!

👉 주황색 원형을 탭했을 때 원형 모양이 커지면서 통통 튕기는 듯한 효과가 나타나고 다시 원래 크기로 되돌아오는 것을 미션으로 받았다.


✔코드

  • 작은 원형 → 큰 원형 → 작은 원형

    처음엔 단순히 원형이 커지고 작아지는 것에만 초점을 맞춰서 140 → 219 → 140이 되는 구현에 신경썼다.

    그랬더니 그냥 일정한 속도로 커지다가 갑자기 뚝하고 140으로 되돌아오는 모습으로 구현됐다. (어색하기 짝이 없었고, 요청된 내용과도 차이가 있어보였다.)

    // 피그마를 보면 Stiffness, Damping, Mass 값이 존재하는 것을 알 수 있다.
      
      sizeAnimation = Tween<double>(begin: 140, end: 219).animate(
        CurvedAnimation(
          parent: sizeAnimationController,
          // curve: Curves.easeOut,  => 기본 사용
          // SpringSimulation 대신 Cubic 베지어 곡선 이용
          curve: const Cubic(0.23, 0.86, 0.29, 1),
        ),
      );

    이를 고려해 직접 값을 줘서 구현해주기로 했다.
    GPT를 통해 curve 구현에 도움을 받기로 한다...

    SpringSimulation 또는 Cubic 베지어 곡선으로 구현 가능했는데, 코드를 보니 Cubic 베지어 곡선이 더 간결해보여 이것으로 선택했다.

    ✅ 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,
           ),
         ),
       );


    ✅ figma spring curve 라이브러리

    final curve = FigmaSpringCurve(250, 31.6, 1);
    final bouncyCurve = FigmaSpringCurve.bouncy;

  • ② 통통 튕기는 Curve

    이건 팀원이 GPT를 통해 알아낸 것을 긁어왔다.
    솔직히 이 부분은 정확히 어떻게 구현해야할지 감이 안 오는 부분이다...

    import 'dart:math';
    
    import 'package:flutter/material.dart';
    
    class CustomBounceCurve extends Curve {
     
     // t =>  애니메이션의 진행 비율
     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);
     }
    }

  • 원형이 커질 때 통통 튕기는 Curve 동시에 적용하기

처음엔 AnimationController를 하나만 만들어서 동시에 구현할 수 있을 거라 생각했는데, 그러면 a 애니메이션이 끝나고 b 애니메이션이 진행되는 형태인 것 같았다.

그래서 AnimationController를 각각 만들어주고 a 애니메이션과 b 애니메이션이 동시에 진행될 수 있도록 했다. (a 애니메이션 = 원형 사이즈 / b 애니메이션 = 통통 튕기는 커브)

     // 원래 크기로 복귀
    sizeAnimationController.addStatusListener(
      (status) async {
        if (status == AnimationStatus.completed) {
          // sizeAnimationController.reverse();
          await Future.delayed(const Duration(microseconds: 200));
          bounceAnimationController.forward();
        }
      },
    );

(+) 의문점🤔
코드를 보니 동시에 진행이라기보단, a 애니메이션이 끝나고 b 애니메이션이 진행되는 형태인 것 같은데...

왜 나는 AnimationController를 각각 만들어주고 a 애니메이션과 b 애니메이션이 동시에 진행되게 만들었다고 생각했던걸까?


솔직히 나에겐 어려웠던...
그래서 팀원의 코드를 참고했고, GPT의 도움도 많이 받았다.
언젠간 나도 안 보고도 챡챡 코딩해내고싶다!

(+) 추가 내용

  • 팀원도 함께 구현한 걸 참고 해서 만들었다!
    코드는 조금 다르다. 같은 내용도 코드가 다르니 신기하다...

    팀원이 더 잘 구현했기 때문에 팀원 벨로그깃허브도 구경가보시길...

  • 디자이너 티스토리

profile
호떡 신문지에서 개발자로 환생

0개의 댓글