Moyo: 円をふよふよアニメーションさせる

August 7, 2019

引き続き、いろんな模様を描いて遊んでいます。

今回は円の線を曲げるアニメーションです。 個人的に、図形描画の練習によく作るものなのですが、今回Flutterでもやってみました。

ソースは以下のとおりです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:vector_math/vector_math.dart' hide Colors;

class FuyoFuyoWidget extends StatefulWidget {
  @override
  _FuyoFuyoWidgetState createState() => _FuyoFuyoWidgetState();
}

class _FuyoFuyoWidgetState extends State<FuyoFuyoWidget>
    with SingleTickerProviderStateMixin {
  double _amplitude = 15;
  Animation<double> _animation;
  AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: Duration(milliseconds: 2000),
      vsync: this,
    );

    _controller.addStatusListener((AnimationStatus status) {
      if (status == AnimationStatus.completed) {
        _controller.reverse();
      }
      if (status == AnimationStatus.dismissed) {
        _controller.forward();
      }
    });

    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    _animation = Tween<double>(begin: 15.0, end: -15.0).animate(_controller)
      ..addListener(() {
        setState(() {
          _amplitude = _animation.value;
        });
      });

    return Container(
      child: Center(
        child: CustomPaint(
          painter: _MyPainter(
            amplitude: _amplitude,
          ),
        ),
      ),
    );
  }

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

class _MyPainter extends CustomPainter {
  _MyPainter({this.amplitude});

  final double amplitude;

  @override
  bool shouldRepaint(_MyPainter oldDelegate) {
    return oldDelegate.amplitude != amplitude;
  }

  @override
  void paint(Canvas canvas, Size size) {
    const double radius = 100;
    const double frequency = 10;

    final Paint stroke = Paint()
      ..color = Colors.black
      ..style = PaintingStyle.stroke
      ..strokeWidth = 1;

    Offset lastPoint;
    for (int i = 0; i <= 360; i += 1) {
      final double angle = radians(i.toDouble());

      final double noise = sin(angle * frequency) * amplitude;
      final double x = (radius + noise) * cos(angle);
      final double y = (radius + noise) * sin(angle);

      final Offset point = Offset(x, y);
      if (lastPoint != null) {
        canvas.drawLine(lastPoint, point, stroke);
      }
      lastPoint = point;
    }
  }
}

ふよふよした円の描き方は以下の記事が参考になりました。(Processingの記事)

https://bencrowder.net/blog/2013/sine-circle-test-animation/

Flutterのアニメーションは以下の記事が参考になりました。

https://medium.com/flutter-community/flutter-custom-painter-circular-wave-animation-bdc65c112690

GitHubのリポジトリはこちらです。 https://github.com/tnantoka/moyo

今回のもFlutter for Webで問題なく動きました。

https://tnantoka.github.io/moyo/