FlutterでLoadingを表すアニメーションWidgetが何個がありますが(例えば、CircularProgressIndicator
とか)、自分なりのアニメーションのカスタマイズしたい場合、CustomPaint
を用いて描くことも可能です。
回転円
まずはシンプルな円回転を描いてみましょう。
下記の例では、AnimationController
の値に応じてアークを連続的に回転させるだけです。
光輪(ハロー)
円の光輪(ハロー)はPaint
のmaskFilterの属性で実現できます。
/// See also:
///
/// * [Canvas.drawShadow], which is a more efficient way to draw shadows.
const MaskFilter.blur(
this._style,
this._sigma,
) : assert(_style != null),
assert(_sigma != null);
上記の属性でぼやけた影を生成できます。パラメーター_sigma
がぼかしの程度を表します。
paint.maskFilter = MaskFilter.blur(BlurStyle.solid, 4);
その_sigma
をアニメーションの値にすると、光輪の動画生成できます。
final Animatable<double> breatheTween = TweenSequence<double>(
<TweenSequenceItem<double>>[
TweenSequenceItem<double>(
tween: Tween<double>(begin: 0, end: 4),
weight: 1,
),
TweenSequenceItem<double>(
tween: Tween<double>(begin: 4, end: 0),
weight: 1,
),
],
).chain(CurveTween(curve: Curves.decelerate));
paint.maskFilter = MaskFilter.blur(BlurStyle.solid, breatheTween.evaluate(animation));
着色
前の章でPathのpaint属性でshader着色を紹介したことあるので、今回をこちらの知識で光輪を着色しようと思います。
// 光輪
paint.maskFilter = MaskFilter.blur(BlurStyle.solid, breatheTween.evaluate(animation));
List<Color> colors = [
Colors.red,
Colors.orange,
Colors.yellow,
Colors.green,
Colors.cyan,
Colors.blue,
Colors.purple,
];
colors.addAll(colors.toList());
final List<double> pos = List.generate(colors.length, (index) => index / colors.length);
// shader
paint.shader = ui.Gradient.sweep(Offset.zero, colors, pos, TileMode.clamp, 0, 2 * pi);
光輪を回転させる
最後は光輪と回転する円を結合すれば、ぐるぐる回るLoading円ができます。
canvas.translate(size.width / 2, size.height / 2);
final Paint paint = Paint()
..style = PaintingStyle.stroke
..color = Colors.purple
..strokeWidth = 1;
// 光輪
paint.maskFilter = MaskFilter.blur(BlurStyle.solid, breatheTween.evaluate(animation));
List<Color> colors = [
Colors.red,
Colors.orange,
Colors.yellow,
Colors.green,
Colors.cyan,
Colors.blue,
Colors.purple,
];
colors.addAll(colors.toList());
final List<double> pos = List.generate(colors.length, (index) => index / colors.length);
// shader
paint.shader = ui.Gradient.sweep(Offset.zero, colors, pos, TileMode.clamp, 0, 2 * pi);
Path path = Path();
path.addOval(Rect.fromCenter(center: Offset.zero, width: 200, height: 200));
canvas.save();
canvas.rotate(animation.value * 2 * pi);
canvas.drawPath(path, paint);
canvas.restore();