Flutter / Animation - Dots

rO_Or·2024년 6월 11일

Dart 그리고 Flutter

목록 보기
15/19

로딩 애니메이션으로 점이 점프하는 듯한 걸 만들어 보자.

class JumpingDots extends StatefulWidget {
  const JumpingDots({
    super.key,
    required this.size,
    required this.dots,
  });

  final double size; // 점 크기
  final int dots; // 점 갯수

  
  State<JumpingDots> createState() => _JumpingDotsState();
}

class _JumpingDotsState extends State<JumpingDots>
    with TickerProviderStateMixin {
    
    // 각 점마다 애니메이션을 주기 위해 List로 선언했다.
    // 위젯이 생성될 때 애니메이션을 적용하기 위함.
  late List<AnimationController> animationControllers;
  late List<Animation<double>> animations;

  
  void initState() {
    super.initState();
    _initAnimations();
  }

  
  void dispose() {
  // 위젯이 페이지에서 사라질 때, 모든 점들의 애니메이션도 dispsoe해줘야 한다.
    for (var controller in animationControllers) {
      controller.dispose();
    }
    super.dispose();
  }

  void _initAnimations() {
  // 리스트 생성으로 애니메이션 컨트롤러 등록.
    animationControllers = List.generate(
      widget.dots,
      (index) {
        return AnimationController(
          vsync: this,
          duration: const Duration(milliseconds: 500),
        );
      },
    );
    
    // 생성된 컨트롤러에 애니메이션 적용.
    animations = List.generate(
      widget.dots,
      (index) {
      	// begin, end가 변할 범위이다.
        return Tween<double>(begin: 0, end: 5).animate(
          CurvedAnimation(
            parent: animationControllers[index],
            curve: Curves.easeInOut,
          ),
        );
      },
    );

	// 애니메이션에 딜레이를 줘서 차례대로? 움직이게 하기.
    for (int i = 0; i < animationControllers.length; i++) {
      Future.delayed(Duration(milliseconds: 300 * i)).then((_) {
        animationControllers[i].repeat(reverse: true);
      });
    }
  }

  
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: List.generate(animationControllers.length, (index) {
      // 애니메이션 빌더를 이용해야 한다.
        return AnimatedBuilder(
          animation: animations[index],
          builder: (context, child) {
          	// Transform 위젯으로 y 값을 변화시킨다.
            return Transform.translate(
              offset: Offset(0, animations[index].value),
              child: Container(
                margin: const EdgeInsets.symmetric(horizontal: 2),
                height: widget.size,
                width: widget.size,
                decoration: const BoxDecoration(
                  color: Colors.black,
                  shape: BoxShape.circle,
                ),
              ),
            );
          },
        );
      }),
    );
  }
}
profile
즐거워지고 싶다.

0개의 댓글