GestureDetectorで図形をぐりぐり回す

May 31, 2019

マウスや指を動かした角度に合わせて何かを動かしたい……わりとよくある要件です。

atan2を使えばなんとかなりそうですが、
数学をまともに修めていない僕はいつも細かいところがわからなくなってしまいます。

そして、いつもこのサイトに助けられています。
(ジオシティーズじゃなくてよかった!)

http://www5d.biglobe.ne.jp/~noocyte/Programming/Geometry/RotationDirection.html#GetAngleAndDirection2

角度を知りたい2点をベクトルとして持ち、dotとcrossを取ってそれをatan2すれば角度が得られます。
三角関数ってすごい!誰でしょう、三角関数が役に立たないとか言ったのは。

GestureDetectorだとこんな感じ書くとradianに角度が入ります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
GestureDetector(
  behavior: HitTestBehavior.opaque,
  child: 何かしらのビュー,
  onPanStart: (DragStartDetails details) {
    _startPosition = details.globalPosition;
  },
  onPanUpdate: (DragUpdateDetails details) {
    final Offset updatedPosition = details.globalPosition;

    final Vector2 a = Vector2(
      _startPosition.dx - center.dx,
      _startPosition.dy - center.dy,
    );
    final Vector2 b = Vector2(
      updatedPosition.dx - center.dx,
      updatedPosition.dy - center.dy,
    );

    final double dot = dot2(a, b);
    final double cross = cross2(a, b);

    final double radian = atan2(cross, dot);
  },
)

ベクトルの演算にはFlutter内でも使われているvector_mathパッケージが使えます。
ただ、Colorsがマテリアルと被るのでご注意ください。

1
import 'package:vector_math/vector_math.dart' hide Colors;

何かしらのビューのところにCustomPaintで図形を描いてみたのがこちらです。

ぐりぐり回せていますね!

全体のソースはGitHubに置いてありますので、気になる方はそちらをご覧ください。

https://github.com/tnantoka/rotate_shape