개발노트

68. [Flutter] Staggered Animation 순차적 애니메이션 효과 만들기 (with CurvedAnimation, Interval) 본문

앱 개발/Flutter

68. [Flutter] Staggered Animation 순차적 애니메이션 효과 만들기 (with CurvedAnimation, Interval)

mroh1226 2024. 2. 19. 14:42
반응형

CurvedAnimation

  • CurvedAnimation: CurvedAnimation 클래스는 다른 애니메이션에 사용되는 애니메이션 커브를 적용하여 애니메이션의 진행 속도를 조절합니다.
  • 주어진 커브 함수를 통해 애니메이션이 시작되거나 끝날 때의 변화량을 조정하여 부드럽게 애니메이션을 진행시킵니다.
  • 이 클래스는 주로 트윈(Tween) 애니메이션과 함께 사용되며, 특히 시작과 끝 사이의 애니메이션을 더 부드럽게 만들어주는 데 유용합니다.
  • CurvedAnimation은 Animation 클래스를 상속하며, 주로 AnimationController의 drive() 메서드를 통해 사용됩니다.

Interval

  • Interval: Interval 클래스는 애니메이션의 특정 구간을 지정하는 데 사용됩니다.
  • 일반적으로 0부터 1까지의 값을 가지며, 애니메이션의 시작과 끝을 나타내는데 사용되고 주로 CurvedAnimation과 함께 사용됩니다.
  • 예를 들어, 애니메이션이 시작되는 시점을 나타내는 값을 0.3으로, 끝나는 시점을 나타내는 값을 0.7로 지정하면, 애니메이션은 전체 기간 중에서 30%에서 70%의 구간에서 실행됩니다.
  • Interval은 CurvedAnimation의 curve 프로퍼티에 전달되어 애니메이션의 구간을 정의합니다.

이 둘을 이용하여 애니메이션을 순차적으로 수행 하고 싶을 때, CurvedAnimation 의 curve: 속성에 Interval() 위젯을 입력하고 수행하고자 하는 진행률 구간을 double형으로 입력합니다.

Interval 에 입력된  AnimationController의 진행률에 따라 curve: 와 함께 특정 구간 애니메이션을 정의할 수 있습니다.


구현 예시.

  • 메뉴 아이콘 버튼 클릭: 현재 화면 Scale축소 > 우측으로 Slid Translate > Stack에 쌓여있던 뒷 화면(Scaffold) 노출
  • 뒷 화면의 X 버튼 클릭 시: 역순으로 수행

 


 

예시 소스.

import 'package:flutter/material.dart';

class TestScreen extends StatefulWidget {
  static String routeName = "testscreen";
  static String routeURL = "testscreen";
  const TestScreen({super.key});

  @override
  State<TestScreen> createState() => _TestScreenState();
}

class _TestScreenState extends State<TestScreen>
    with SingleTickerProviderStateMixin {
  //애니메이션 컨트롤러
  late final AnimationController _animationController = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 2),
      reverseDuration: const Duration(seconds: 1));

  //trans를 위한 Animation<Offset>
  late final Animation<Offset> _trans =
      Tween(begin: const Offset(0, 0), end: const Offset(0.5, 0)).animate(
          //애니메이션에 커브감 주기
          CurvedAnimation(
              parent: _animationController,
              curve:
                  //AnimationController 진행률이 50% ~ 100% 일때 수행
                  const Interval(0.5, 1.0,
                      curve: Curves.fastLinearToSlowEaseIn)));

  //scale을 위한 Animation<Offset>
  late final Animation<double> _scale =
      Tween(begin: 1.0, end: 0.6).animate(CurvedAnimation(
          parent: _animationController,
          curve:
              //AnimationController 진행률이 0% ~ 50% 일때 수행
              const Interval(0.0, 0.5, curve: Curves.fastOutSlowIn)));

  //클릭 했을 때 애니메이션효과 실행
  void onTapforward() {
    _animationController.forward();
  }

  //클릭 했을 때 애니메이션효과 거꾸로 실행
  void onTapReverse() {
    _animationController.reverse();
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Scaffold(
          appBar: AppBar(
            leading: IconButton(
              icon: const Icon(Icons.close),
              onPressed: onTapReverse,
            ),
          ),
          backgroundColor: Colors.blue,
          body: const Center(
            child: Text("첫번쨰 Stack 화면"),
          ),
        ),
        SlideTransition(
          position: _trans,
          child: ScaleTransition(
            scale: _scale,
            child: Scaffold(
              appBar: AppBar(
                backgroundColor: Colors.transparent,
                elevation: 0,
                actions: [
                  IconButton(
                    icon: const Icon(Icons.menu),
                    onPressed: onTapforward,
                  )
                ],
              ),
              backgroundColor: Colors.green,
              body: const Center(
                child: Text("두번째 Stack 화면"),
              ),
            ),
          ),
        )
      ],
    );
  }
}

소스 설명.

 late final Animation<Offset> _trans =
      Tween(begin: const Offset(0, 0), end: const Offset(0.5, 0)).animate(
          //애니메이션에 커브감 주기
          CurvedAnimation(
              parent: _animationController,
              curve:
                  //AnimationController 진행률이 50% ~ 100% 일때 수행
                  const Interval(0.5, 1.0,
                      curve: Curves.fastLinearToSlowEaseIn)));

 

  1. AnimationController를 넣는 animate() 안에 CurvedAnimation을 넣어줍니다.
  2. CurvedAnimation 의 parent: 속성에 AnimationController를 입력합니다.
  3. CurvedAnimation 의 curve:속성에 Interval(시작지점, 끝지점) 을 입력합니다.
    (0.0 ~ 1.0 안에서 입력, Interval(0.0, 0.5)일 경우 0% ~ 50% 진행률에서 수행함을 의미함)
  4. Interval 의 curve:속성에 수행할 curve를 입력해줍니다.
  5. AnimationController.forward()를 호출하면 위에서 설정한 특정 구간에 애니메이션이 수행됩니다.
  6. AnimationController.reverse()를 호출하면 역순으로 수행됩니다.
반응형
Comments