目的
FlutterのCustomPaint を用いて単振動のアニメーションを描くことです。
前提知識
単振動とは
単振動とは、最も基本的な振動のことで等速円運動を、その円の直径上に投影したのと同じように動く、物体の往復運動のこと。 このとき、往復に要する時間を周期、振動半径を振幅という。
方程式
$$
{\displaystyle x=A\cos(\omega t+\phi )}
$$
等速円運動の周期を T [s]
角速度を ω [rad/s]
回転数を f [Hz]
円の半径を A [m]
単振動は、正弦波と密接な関係がある運動です。等速円運動と単振動と正弦波は密接な関係があります。これらにおいては以下の式が一般的に成り立ちます。
$$
{\displaystyle f={\frac 1T}}
$$
$$
{\displaystyle ω = 2πf = {\frac {2π}T}}
$$
単振動は、次のように円上を等速運動する点を直線上へ投影したものとも見なせる。xy-平面上に、始点 O、終点 P、一定長さ A の幾何ベクトル OP を考える。点 P が点 O を中心として一定速度 ω で反時計回りに回転しており、t = 0 で点 P は角度 φ の位置にあるとする。この点を x 軸に正射影すると、
$$
{\displaystyle x=A\cos(\omega t+\phi )}
$$
となり、y 軸に射影すると、
$$
{\displaystyle y=A\sin(\omega t+\phi )}
$$
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F2491433%2F7402f6b9-7603-c503-d690-a9a385381893.gif?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=7b111dff4b573733a23d355936b3d6f3)
Flutterのアニメーション知識
下記本のアニメーション篇を確認ください。
Flutterでアニメーション
まずは、球体移動の座標x,yを求める
late AnimationController _ctrl;
final Duration animDuration = const Duration(milliseconds: 2000);
@override
void initState() {
super.initState();
_ctrl = AnimationController(
duration: animDuration,
lowerBound: 0,
upperBound: 2 * pi,
vsync: this,
);
}
double value = _ctrl.value;
double get x => cos(value);
double get y => sin(value);
次は1つの球体単振動のアニメーションを作る
canvas.translate(size.width / 2, size.height / 2);
Path path = Path();
Paint paint = Paint()
..style = PaintingStyle.stroke
..color = Colors.red
..strokeWidth = 1;
path.addOval(Rect.fromCircle(center: Offset.zero, radius: 100));
// 破線path
path = DashPath().dashPath(path);
canvas.drawPath(path, paint);
path.reset();
path.addOval(Rect.fromCircle(center: Offset(0, y * 100), radius: 10));
canvas.drawPath(
path,
paint
..style = PaintingStyle.fill
..color = Colors.purple,
);
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F2491433%2Ff4ccc72b-b6b2-bd21-75ad-07e7c08e2e74.gif?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=922752122d2ae7c351d53124b048abf1)
1個目できたので、2つ、3つ...8つも簡単です。
path.reset();
value = value + pi * 0.125;
canvas.rotate(pi * 0.125);
path.addOval(Rect.fromCircle(center: Offset(0, y * 100), radius: 10));
canvas.drawPath(
path,
paint
..style = PaintingStyle.fill
..color = Colors.purple,
);
2つ | 8つ |
---|---|
![]() |
![]() |
リポジトリ