Fultterで紙吹雪を出す方法を紹介します。
・Flutter 2.2.0
・Dart 2.13.0
・confetti 0.6.0-nullsafety
まずconfettiをインストールします。pubspec.yamlに以下を追記し、次いでPub getをクリックします。
confetti: ^0.6.0-nullsafetys
そして紙吹雪を出したいファイルで以下を宣言します。
import 'package:confetti/confetti.dart';
以下のようにコントローラを宣言します。
final _controller =
ConfettiController(duration: const Duration(milliseconds: 500));
durationは紙吹雪を何秒出すかの設定です。例えばここをseconds: 10
にしたら紙吹雪が10秒間出続けます。
ConfettiWidget()が紙吹雪を出すウィジェットになります。これをbuild関数の中に追加し、confettiControllerプロパティに先ほど宣言した_controllerを設定します。
ConfettiWidget(
confettiController: _controller,
)
この1行が走れば紙吹雪が舞います。
_controller.play();
ConfettiWidgetにはさまざまなプロパティがあります。お好みで設定して使いましょう。
blastDirectionality
プロパティにexplosive
かdirectional
のどちらかを設定します。
explosive
は爆発するように中央からランダムな方向に紙吹雪が噴出します。なので方向を指定する必要がありません。
directional
は一定方向に噴出します。こちらはblastDirection
で方向を指定する必要があります。
ConfettiWidget(
confettiController: _controller,
blastDirectionality: BlastDirectionality.explosive,
);
blastDirection
プロパティに方向を設定します。
piはπのことです。0(2π)で右、π/2で下、πで左、3π/2で上。なぜか数学でやった単位円と逆まわりですね。
import 'dart:math';
ConfettiWidget(
confettiController: _controller,
blastDirectionality: BlastDirectionality.directional,
blastDirection: pi / 2,
);
emissionFrequency
プロパティで紙吹雪が放出される頻度を設定します。
0〜1の値にする必要があり、値が大きいほど紙吹雪が放出される頻度が増えます。
ConfettiWidget(
confettiController: _controller,
emissionFrequency: 1,
);
numberOfParticles
プロパティで一度に発射する紙の数を設定します。
デフォルトは10です。
ConfettiWidget(
confettiController: _controller,
numberOfParticles: 30,
);
shouldLoop
プロパティで繰り返すかどうかの設定をします。
デフォルトはfalseです。
ConfettiWidget(
confettiController: _controller,
shouldLoop: false,
);
maxBlastForce
とminBlastForce
に噴出初速の最大値と最小値を設定します。
デフォルトは最大20、最小5です。
ConfettiWidget(
confettiController: _controller,
maxBlastForce: 5,
minBlastForce: 2,
);
displayTarget
をtrueにすることで紙吹雪の発射位置に印がついてわかりやすくなります。
デフォルトはfalseです。
ConfettiWidget(
confettiController: _controller,
displayTarget: true,
);
colors
プロパティに色を設定できます。設定しなかった場合色はランダムになります。
ConfettiWidget(
confettiController: _controller,
colors: [Colors.green, Colors.pink,Colors.orange],
);
maximumSize
プロパティで紙吹雪のサイズの最大値を、minimumSize
プロパティで紙吹雪のサイズの最小値を設定します。
たとえば、minimumSizeをSize(10,10)、maximumSizeをSize(50,50)に設定すると、最小サイズ(10、10)と最大サイズ(50、50)[幅、高さ]の間のサイズの紙吹雪が作成されます。
ConfettiWidget(
confettiController: _controller,
maximumSize: Size(40, 40),
minimumSize: Size(20, 20),
);
gravity
プロパティに紙の落ちる速さを設定します。
0〜1の値にする必要があり、値が大きいほど速く落ちます。デフォルトは0.1です。
ConfettiWidget(
confettiController: _controller,
gravity: 0.3,
);
particleDrag
プロパティに抗力を設定します。
抗力は空気抵抗みたいなイメージです。0〜1の値にする必要があります。値が大きいほど、散らばらずゆっくりと落ちていきます。デフォルトは0.05です。
ConfettiWidget(
confettiController: _controller,
particleDrag: 0.001,
);
canvas
プロパティで紙吹雪が表示される領域のサイズを設定します。
デフォルトでは、フルスクリーンサイズに設定されています。
ConfettiWidget(
confettiController: _controller,
canvas: Size(100, 100),
);
createParticlePath
プロパティに紙吹雪の形を設定できます。
デフォルトは長方形です。
ConfettiWidget(
confettiController: _controller,
createParticlePath: drawStar,
);
カスタムcreateParticlePathの例
Path drawStar(Size size) {
// Method to convert degree to radians
double degToRad(double deg) => deg * (pi / 180.0);
const numberOfPoints = 5;
final halfWidth = size.width / 2;
final externalRadius = halfWidth;
final internalRadius = halfWidth / 2.5;
final degreesPerStep = degToRad(360 / numberOfPoints);
final halfDegreesPerStep = degreesPerStep / 2;
final path = Path();
final fullAngle = degToRad(360);
path.moveTo(size.width, halfWidth);
for (double step = 0; step < fullAngle; step += degreesPerStep) {
path.lineTo(halfWidth + externalRadius * cos(step),
halfWidth + externalRadius * sin(step));
path.lineTo(halfWidth + internalRadius * cos(step + halfDegreesPerStep),
halfWidth + internalRadius * sin(step + halfDegreesPerStep));
}
path.close();
return path;
}
参考までにサンプルアプリのコードを載せておきます。
import 'package:flutter/material.dart';
import 'package:confetti/confetti.dart';
import 'dart:math';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _controller =
ConfettiController(duration: const Duration(milliseconds: 500));
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('紙吹雪サンプル'),
),
body: Stack(
children: [
Center(
child: ElevatedButton(
child: Text('紙吹雪舞わせる'),
onPressed: () {
_controller.play();
},
),
),
Container(
padding: EdgeInsets.all(30),
alignment: Alignment.topCenter,
child: _buildConfetti(),
),
],
),
);
}
Widget _buildConfetti() {
return ConfettiWidget(
confettiController: _controller,
blastDirectionality: BlastDirectionality.explosive,
// blastDirection: pi / 2,
emissionFrequency: 1,
numberOfParticles: 30,
shouldLoop: false,
maxBlastForce: 5,
minBlastForce: 2,
displayTarget: true,
colors: [Colors.green, Colors.pink, Colors.orange],
maximumSize: Size(40, 40),
minimumSize: Size(20, 20),
gravity: 0.3,
particleDrag: 0.001,
// canvas: Size(100, 100),
createParticlePath: drawStar,
);
}
Path drawStar(Size size) {
// Method to convert degree to radians
double degToRad(double deg) => deg * (pi / 180.0);
const numberOfPoints = 5;
final halfWidth = size.width / 2;
final externalRadius = halfWidth;
final internalRadius = halfWidth / 2.5;
final degreesPerStep = degToRad(360 / numberOfPoints);
final halfDegreesPerStep = degreesPerStep / 2;
final path = Path();
final fullAngle = degToRad(360);
path.moveTo(size.width, halfWidth);
for (double step = 0; step < fullAngle; step += degreesPerStep) {
path.lineTo(halfWidth + externalRadius * cos(step),
halfWidth + externalRadius * sin(step));
path.lineTo(halfWidth + internalRadius * cos(step + halfDegreesPerStep),
halfWidth + internalRadius * sin(step + halfDegreesPerStep));
}
path.close();
return path;
}
}
可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。
Read More可茂IT塾ではFlutterインターンを募集しています!可茂IT塾のエンジニアの判断で、一定以上のスキルをを習得した方には有給でのインターンも受け入れています。
Read More