import 'package:flutter/material.dart';
class GestureAngleView extends StatelessWidget{
final double angel;
final Function(double angel, bool end) onChanged; final List Function(BuildContext context, Size size, double radian)buildChildren;
const GestureAngleView(this.angel, this.onChanged, this.buildChildren);
@override Widget build(BuildContext context) { return GestureView( builder: (context, size) { return Stack( alignment:Alignment.center , children: buildChildren(context, size, angel / 180 * pi), ); }, onChanged: (point, size, isEnd) { turn(point, size, isEnd); }, ); }
void turn(Offset point, Size size, bool isEnd){ var radian = getRadians(size.center(Offset.zero), point); var angel = getAngel(radian); onChanged(angel, isEnd); }
double getRadius(Offset point, Offset center) { return sqrt(pow((point.dx - center.dx), 2) + pow(point.dy - center.dy, 2)); }
double getRadians(Offset center, Offset point) { var a = point.dx - center.dx; var b = center.dy - point.dy; double radians = atan2(b, a); return radians < 0 ? -radians : 2 * pi - radians; }
double getAngel(double radian) { if(radian >= 2 * pi) { radian -= 2 * pi; } if(radian < 0) { radian += 2 * pi; }
return (radian / pi) * 180;
}
}
class GestureView extends StatefulWidget {
final Function(Offset point, Size size, bool end) onChanged; final Widget Function(BuildContext context, Size size) builder;
const GestureView({@required this.builder, @required this.onChanged, Key key}) : super(key: key);
@override State createState() => _GestureState();
} class _GestureState extends State {
Offset point; Size size;
@override Widget build(BuildContext context) { return LayoutBuilder(builder: (BuildContext ctx, BoxConstraints constraints) { double width = constraints.maxWidth; double height = constraints.maxHeight;
size = Size(width, height);
return Center(child: GestureDetector(
onHorizontalDragDown: (DragDownDetails details) => turn(details.globalPosition, details.localPosition),
onHorizontalDragUpdate: (DragUpdateDetails details) => turn(details.globalPosition, details.localPosition),
onHorizontalDragEnd: (DragEndDetails details) => widget.onChanged(point, size, true),
onVerticalDragDown: (DragDownDetails details) => turn(details.globalPosition, details.localPosition),
onVerticalDragUpdate: (DragUpdateDetails details) => turn(details.globalPosition, details.localPosition),
onVerticalDragEnd: (DragEndDetails details) => widget.onChanged(point, size, true),
child: SizedBox(
width: width,
height: height,
child: widget.builder(context, size),
),
),);
},);
}
void turn(Offset globalPosition, Offset localPosition){ point = localPosition; widget.onChanged(point, size, false); }
}