본문 바로가기
Flutter

[Flutter] ConfettiWidget shape customize

by Banlim 2021. 4. 26.

[나중에 참고하려고 기록]

 

현재 진행하고 있는 프로젝트에서 생일 폭죽처럼 색종이 조각들을 터뜨려주는 애니메이션이 구현되어있었다. ConfettiWidget을 사용하여 해당 애니메이션이 구현되었으며, 모양은 직사각형이 default였다. 이 때, Confetti package의 예제 코드를 살펴보니 Path를 사용해서 내가 원하는 모양의 색종이 조각을 만들 수 있었다.

 

// Flutter package : Confetti Package

pub.dev/packages/confetti

 

confetti | Flutter Package

Blast colorful confetti all over the screen. Celebrate in app achievements with style. Control the velocity, angle, gravity and amount of confetti.

pub.dev

 

우선 ConfettiWidget을 사용하기 위해 pubspec.yaml 파일에 해당 패키지를 넣는다

 

// pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  
  confetti: ^0.5.5
  . . .

 

다음으로, 본인이 출력하고자 하는 페이지에 ConfettiController를 선언하고, 생성한다. (dispose도 같이 해준다.)

. . .

ConfettiController _controllerCenter;

  @override
  void initState() {
    _controllerCenter =
        ConfettiController(duration: const Duration(seconds: 10));
    super.initState();
  }

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

 

다음으로 Confetti 예제처럼 아래와 같이 코드를 작성해준다.

여기서 createParticlePath 부분이 중요하다! 이 코드에서 내가 원하는 모양으로 커스터마이징을 할 수 있다.

Widget build(BuildContext context) {
    return SafeArea(
      child: Stack(
        children: <Widget>[
          //CENTER -- Blast
          Align(
            alignment: Alignment.center,
            child: ConfettiWidget(
              confettiController: _controllerCenter,
              blastDirectionality: BlastDirectionality
                  .explosive, // don't specify a direction, blast randomly
              shouldLoop:
              true, // start again as soon as the animation is finished
              colors: const [
                Colors.green,
                Colors.blue,
                Colors.pink,
                Colors.orange,
                Colors.purple
              ], 
              createParticlePath: drawHeart,
            ),
          ),
          Align(
            alignment: Alignment.center,
            child: TextButton(
                onPressed: () {
                  _controllerCenter.play();
                },
                child: _display('blast\nHearts')),
          ),
        ],
      ),
    );
  }

 

여기서 내가 원하는 모양은 하트 모양의 색종이 조각들이 흩날리는 것이었다. 따라서 하트 모양 Path를 리턴해주는 메서드를 아래와 같이 작성한다.

해당 메서드를 작성한 후, 바로 위 코드에 나와있는 createParticlePath : drawHeart, 라고 작성하여 해당 모양을 출력하도록 넣어준다.

 

// 하트 모양 Path 메서드

Path drawHeart(Size size) {
    double width = size.width;
    double height = size.height;

    Path path = Path();

    path.moveTo(0.5 * width, height * 0.35);
    path.cubicTo(0.2 * width, height * 0.1, -0.25 * width, height * 0.6,
        0.5 * width, height);
    path.moveTo(0.5 * width, height * 0.35);
    path.cubicTo(0.8 * width, height * 0.1, 1.25 * width, height * 0.6,
        0.5 * width, height);

    path.close();
    return path;
  }

 

실행해주면 아래 사진과 같다.

 

 

// Full Code

// (실제 프로젝트에서는 예제처럼 main에 넣지 않고, 필요한 부분에 넣었다.

// 이 글의 Full code는 Confetti package의 example 코드를 기준으로 작성되었다.

 

import 'dart:math';

import 'package:confetti/confetti.dart';
import 'package:flutter/material.dart';

void main() => runApp(const ConfettiSample());

class ConfettiSample extends StatelessWidget {
  const ConfettiSample({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Confetti',
        home: Scaffold(
          backgroundColor: Colors.grey[900],
          body: MyApp(),
        ));
  }
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  ConfettiController _controllerCenter;

  @override
  void initState() {
    _controllerCenter =
        ConfettiController(duration: const Duration(seconds: 10));
    super.initState();
  }

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

  Path drawHeart(Size size) {
    double width = size.width;
    double height = size.height;

    Path path = Path();

    path.moveTo(0.5 * width, height * 0.35);
    path.cubicTo(0.2 * width, height * 0.1, -0.25 * width, height * 0.6,
        0.5 * width, height);
    path.moveTo(0.5 * width, height * 0.35);
    path.cubicTo(0.8 * width, height * 0.1, 1.25 * width, height * 0.6,
        0.5 * width, height);

    path.close();
    return path;
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Stack(
        children: <Widget>[
          //CENTER -- Blast
          Align(
            alignment: Alignment.center,
            child: ConfettiWidget(
              confettiController: _controllerCenter,
              blastDirectionality: BlastDirectionality
                  .explosive,
              shouldLoop:
              true, 
              colors: const [
                Colors.green,
                Colors.blue,
                Colors.pink,
                Colors.orange,
                Colors.purple
              ], 
              createParticlePath: drawHeart,
            ),
          ),
          Align(
            alignment: Alignment.center,
            child: TextButton(
                onPressed: () {
                  _controllerCenter.play();
                },
                child: _display('blast\nHearts')),
          ),
        ],
      ),
    );
  }

  Text _display(String text) {
    return Text(
      text,
      style: const TextStyle(color: Colors.white, fontSize: 20),
    );
  }
}

 

 

// Path -> 하트 모양 만들기 참고한 링크

stackoverflow.com/questions/57756692/flutter-drawing-a-heart-shape-with-custompainter

 

Flutter drawing a heart shape with CustomPainter

I'm wondering if anyone has any pointers on how to get started on drawing a heart shape in flutter with CustomPainter. I've managed to draw things like triangles and squares, or a basic circle, but a

stackoverflow.com