Dart 飞镖颤振:如何绕圆圈旋转?
如何让正方形对手势检测器做出响应 围绕一个圆旋转正方形。顺时针转动它应该会 从0到360的正增长和逆时针方向的负增长应从 360比0。但在这里,它增加到超过360,也低于0 负值。对阻力的反应是不可预测的 只有在检测到手势而不是圆时,正方形才应该旋转 在它后面 我不知道这是否是解决问题的方法。任何帮助都是非常有用的 非常感谢。我已经干了好几天了Dart 飞镖颤振:如何绕圆圈旋转?,dart,flutter,Dart,Flutter,如何让正方形对手势检测器做出响应 围绕一个圆旋转正方形。顺时针转动它应该会 从0到360的正增长和逆时针方向的负增长应从 360比0。但在这里,它增加到超过360,也低于0 负值。对阻力的反应是不可预测的 只有在检测到手势而不是圆时,正方形才应该旋转 在它后面 我不知道这是否是解决问题的方法。任何帮助都是非常有用的 非常感谢。我已经干了好几天了 import 'dart:math'; import 'package:flutter/material.dart'; import 'package:
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
runApp(new MyRotateApp());
}
class MyRotateApp extends StatefulWidget {
@override
MyRotateAppState createState() {
return new MyRotateAppState();
}
}
class MyRotateAppState extends State<MyRotateApp> {
double angleDelta;
String strDialAngle;
@override
void initState() {
angleDelta = -90.0; //start from top position
strDialAngle = 'Angle Text';
super.initState();
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(title: new Text('ROTATE Square')),
body: new Center(
child: new Stack(alignment: Alignment.center,
children: <Widget>[
new Container(
height: 350.0,
decoration: new BoxDecoration(
color: Colors.blueGrey, shape: BoxShape.circle),
),
/// position the square
new MyRadialPosition(
radius: 130.0,
angle: angleDelta * PI / 180.0,
/// Gesture Detector
child: new GestureDetector(
onVerticalDragUpdate: _onVerticalDragUpdate,
onHorizontalDragUpdate: _onHorizontalDragUpdate,
child: new Container(
width: 45.0,
height: 45.0,
color: Colors.green,
),
)),
/// update text based on angle value of rotation of square
new Padding(
padding: const EdgeInsets.only(bottom: 80.0),
child: new Text('$strDialAngle',
style: new TextStyle(fontSize: 25.0,color: Colors.white),),
),
],
),
),
));
}
void _onVerticalDragUpdate(DragUpdateDetails details) {
angleDelta = angleDelta + (details.delta.dy).roundToDouble();
strDialAngle = 'VERTICAL Drag : ${angleDelta + 90.0}';
setState((){});
}
void _onHorizontalDragUpdate(DragUpdateDetails details) {
angleDelta = angleDelta + (details.delta.dx).roundToDouble();
strDialAngle = 'Horizontal Drag : ${angleDelta + 90.0}';
setState((){});
}
}
class MyRadialPosition extends StatelessWidget {
final double radius;
final double angle;
final Widget child;
MyRadialPosition({this.radius, this.angle, this.child});
@override
Widget build(BuildContext context) {
final x = radius * cos(angle);
final y = radius * sin(angle);
return new Transform(
transform: new Matrix4.translationValues(x, y, 0.0),
child: child,);
}
}
// for adding to the above Stack RadialDragGestureDetector
new MyRadialPosition(radius: 170.0,
angle: angleDelta * PI / 180.0,
child: new RadialDragGestureDetector(
onRadialDragUpdate: _onRadialDragUpdate,
child: new Container(
width: 45.0,
height: 45.0,
color: Colors.amber,
),
),
),
_onRadialDragUpdate(PolarCoord updateCoord) {
setState((){
angleDelta = (updateCoord.angle).roundToDouble();
print('updateCoord.angle : ${(updateCoord.angle).roundToDouble()}');
});
}
import'dart:math';
进口“包装:颤振/材料.省道”;
导入“包:flifter/services.dart”;
void main(){
SystemChrome.setPreferredOrientations(
[设备定向。肖像向上,设备定向。肖像向下];
runApp(新的MyRotateApp());
}
类MyRotateApp扩展StatefulWidget{
@凌驾
MyRotateAppState createState(){
返回新的MyRotateAppState();
}
}
类MyRotateAppState扩展状态{
双三角洲;
字符串字符串;
@凌驾
void initState(){
角度增量=-90.0;//从顶部位置开始
strDialAngle='角度文本';
super.initState();
}
@凌驾
小部件构建(构建上下文){
返回新材料PP(
家:新脚手架(
appBar:new appBar(标题:新文本('ROTATE Square')),
正文:新中心(
子级:新堆栈(对齐方式:alignment.center,
儿童:[
新容器(
高度:350.0,
装饰:新盒子装饰(
颜色:颜色。蓝灰色,形状:长方形。圆形),
),
///定位广场
新散瞳位置(
半径:130.0,
角度:角度增量*PI/180.0,
///手势检测器
儿童:新的手势检测器(
垂直排水日期:_垂直排水日期,
onHorizontalDragUpdate:_onHorizontalDragUpdate,
子容器:新容器(
宽度:45.0,
身高:45.0,
颜色:颜色。绿色,
),
)),
///基于正方形旋转的角度值更新文本
新填料(
填充:仅限常量边集(底部:80.0),
子项:新文本(“$STRIALangle”,
样式:新的文本样式(fontSize:25.0,颜色:Colors.white),
),
],
),
),
));
}
void _onVerticalDragUpdate(DragUpdateDetails){
angleDelta=angleDelta+(details.delta.dy).roundToDouble();
strDialAngle='垂直阻力:${angleDelta+90.0}';
setState((){});
}
void _onHorizontalDragUpdate(DragUpdate详细信息){
angleDelta=angleDelta+(details.delta.dx).roundToDouble();
strDialAngle='水平阻力:${angleDelta+90.0}';
setState((){});
}
}
类MyRadialPosition扩展了无状态小部件{
最终双半径;
最终双角度;
最后一个孩子;
MyRadialPosition({this.radius,this.angle,this.child});
@凌驾
小部件构建(构建上下文){
最终x=半径*cos(角度);
最终y=半径*sin(角度);
返回新变换(
转换:新矩阵4.转换值(x,y,0.0),
孩子:孩子,);
}
}
//用于添加到上面的堆栈RadialDragGestureDetector
新半径位置(半径:170.0,
角度:角度增量*PI/180.0,
儿童:新的放射性碎片探测器(
onRadialDragUpdate:\u onRadialDragUpdate,
子容器:新容器(
宽度:45.0,
身高:45.0,
颜色:颜色。琥珀色,
),
),
),
_onRadialDragUpdate(PolarCoord更新命令){
设置状态(){
angleDelta=(updatecord.angle).roundToDouble();
打印('updatecord.angle:${(updatecord.angle.roundToDouble()}');
});
}
您可以使用。是的
而监听器在启动和更新时会获得PolarCoord
,这样您就可以看到弧度
您没有提到您是否做了一个或两个手指手势,因此请告诉我这是否有帮助,您可以使用onPanUpdate
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:math';
class MyRotateApp extends StatefulWidget {
@override
MyRotateAppState createState() {
return new MyRotateAppState();
}
}
class MyRotateAppState extends State<MyRotateApp> {
double angleDelta;
String strDialAngle;
@override
void initState() {
angleDelta = -90.0; //start from top position
strDialAngle = 'Angle Text';
super.initState();
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(title: new Text('ROTATE Square')),
body: new Center(
child: new Stack(alignment: Alignment.center,
children: <Widget>[
new Container(
height: 260.0,
width: 260.0,
decoration: new BoxDecoration(
color: Colors.blueGrey, shape: BoxShape.circle),
),
/// position the square
new MyRadialPosition(
radius: 130.0,
angle: angleDelta * 3.142 / 180.0,
/// Gesture Detector
child: new GestureDetector(
onPanUpdate: _onPanUpdate,
// onVerticalDragUpdate: _onVerticalDragUpdate,
// onHorizontalDragUpdate: _onHorizontalDragUpdate,
child: new Container(
width: 45.0,
height: 45.0,
color: Colors.green,
),
)),
/// update text based on angle value of rotation of square
new Padding(
padding: const EdgeInsets.only(bottom: 80.0),
child: new Text('$strDialAngle',
style: new TextStyle(fontSize: 25.0,color: Colors.white),),
),
],
),
),
));
}
void _onVerticalDragUpdate(DragUpdateDetails details) {
angleDelta = angleDelta + (details.delta.dy).roundToDouble();
strDialAngle = 'VERTICAL Drag : ${angleDelta + 90.0}';
setState((){});
}
void _onHorizontalDragUpdate(DragUpdateDetails details) {
angleDelta = angleDelta + (details.delta.dx).roundToDouble();
strDialAngle = 'Horizontal Drag : ${angleDelta + 90.0}';
setState((){});
}
//use onPanUpdate here
void _onPanUpdate(DragUpdateDetails details) {
Offset center = Offset(130.0, 130.0);
var a = (details.delta.dx) - center.dx;
var b = center.dy - (details.delta.dy);
angleDelta = angleDelta + atan2(b, a);
setState(() {
});
}
}
class MyRadialPosition extends StatelessWidget {
final double radius;
final double angle;
final Widget child;
MyRadialPosition({this.radius, this.angle, this.child});
@override
Widget build(BuildContext context) {
final x = radius * cos(angle);
final y = radius * sin(angle);
return new Transform(
transform: new Matrix4.translationValues(x, y, 0.0),
child: child,);
}
}
导入“包装:颤振/材料.省道”;
导入“包:flifter/services.dart”;
导入“dart:math”;
类MyRotateApp扩展StatefulWidget{
@凌驾
MyRotateAppState createState(){
返回新的MyRotateAppState();
}
}
类MyRotateAppState扩展状态{
双三角洲;
字符串字符串;
@凌驾
void initState(){
角度增量=-90.0;//从顶部位置开始
strDialAngle='角度文本';
super.initState();
}
@凌驾
小部件构建(构建上下文){
返回新材料PP(
家:新脚手架(
appBar:new appBar(标题:新文本('ROTATE Square')),
正文:新中心(
子级:新堆栈(对齐方式:alignment.center,
儿童:[
新容器(
身高:260.0,
宽度:260.0,
装饰:新盒子装饰(
颜色:颜色。蓝灰色,形状:长方形。圆形),
),
///定位广场
新散瞳位置(
半径:130.0,
角度:角度增量*3.142/180.0,
///手势检测器
儿童:新的手势检测器(
onPanUpdate:_onPanUpdate,
//垂直排水日期:_垂直排水日期,
//onHorizontalDragUpdate:_onHorizontalDragUpdate,
子容器:新容器(
宽度:45.0,
身高:45.0,
颜色:颜色。绿色,
),
)),
///基于正方形旋转的角度值更新文本
新填料(
填充:仅限常量边集(底部:80.0),
子项:新文本(“$STRIALangle”,
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:math';
class MyRotateApp extends StatefulWidget {
@override
MyRotateAppState createState() {
return new MyRotateAppState();
}
}
class MyRotateAppState extends State<MyRotateApp> {
double angleDelta;
String strDialAngle;
@override
void initState() {
angleDelta = -90.0; //start from top position
strDialAngle = 'Angle Text';
super.initState();
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(title: new Text('ROTATE Square')),
body: new Center(
child: new Stack(alignment: Alignment.center,
children: <Widget>[
new Container(
height: 260.0,
width: 260.0,
decoration: new BoxDecoration(
color: Colors.blueGrey, shape: BoxShape.circle),
),
/// position the square
new MyRadialPosition(
radius: 130.0,
angle: angleDelta * 3.142 / 180.0,
/// Gesture Detector
child: new GestureDetector(
onPanUpdate: _onPanUpdate,
// onVerticalDragUpdate: _onVerticalDragUpdate,
// onHorizontalDragUpdate: _onHorizontalDragUpdate,
child: new Container(
width: 45.0,
height: 45.0,
color: Colors.green,
),
)),
/// update text based on angle value of rotation of square
new Padding(
padding: const EdgeInsets.only(bottom: 80.0),
child: new Text('$strDialAngle',
style: new TextStyle(fontSize: 25.0,color: Colors.white),),
),
],
),
),
));
}
void _onVerticalDragUpdate(DragUpdateDetails details) {
angleDelta = angleDelta + (details.delta.dy).roundToDouble();
strDialAngle = 'VERTICAL Drag : ${angleDelta + 90.0}';
setState((){});
}
void _onHorizontalDragUpdate(DragUpdateDetails details) {
angleDelta = angleDelta + (details.delta.dx).roundToDouble();
strDialAngle = 'Horizontal Drag : ${angleDelta + 90.0}';
setState((){});
}
//use onPanUpdate here
void _onPanUpdate(DragUpdateDetails details) {
Offset center = Offset(130.0, 130.0);
var a = (details.delta.dx) - center.dx;
var b = center.dy - (details.delta.dy);
angleDelta = angleDelta + atan2(b, a);
setState(() {
});
}
}
class MyRadialPosition extends StatelessWidget {
final double radius;
final double angle;
final Widget child;
MyRadialPosition({this.radius, this.angle, this.child});
@override
Widget build(BuildContext context) {
final x = radius * cos(angle);
final y = radius * sin(angle);
return new Transform(
transform: new Matrix4.translationValues(x, y, 0.0),
child: child,);
}
}
_panUpdateHandler(DragUpdateDetails d) {
/// Pan location on the wheel
bool onTop = d.localPosition.dy <= radius;
bool onLeftSide = d.localPosition.dx <= radius;
bool onRightSide = !onLeftSide;
bool onBottom = !onTop;
/// Pan movements
bool panUp = d.delta.dy <= 0.0;
bool panLeft = d.delta.dx <= 0.0;
bool panRight = !panLeft;
bool panDown = !panUp;
/// Absolute change on axis
double yChange = d.delta.dy.abs();
double xChange = d.delta.dx.abs();
/// Directional change on wheel
double verticalRotation = (onRightSide && panDown) || (onLeftSide && panUp)
? yChange
: yChange * -1;
double horizontalRotation =
(onTop && panRight) || (onBottom && panLeft) ? xChange : xChange * -1;
// Total computed change
double rotationalChange = verticalRotation + horizontalRotation;
double _value = degree + (rotationalChange / 5);
setState(() {
degree = _value > 0 ? _value : 0;
ctrl.value = degree;
});
}
_panEndHandler(DragEndDetails d) {
ctrl
.animateTo(roundToBase(degree.roundToDouble(), 10),
duration: Duration(milliseconds: 551), curve: Curves.easeOutBack)
.whenComplete(() {
setState(() {
degree = roundToBase(degree.roundToDouble(), 10);
});
});
}
GestureDetector draggableWheel = GestureDetector(
onPanUpdate: _panUpdateHandler,
onPanEnd: _panEndHandler,
child: Stack(
children: [
AnimatedBuilder(
animation: ctrl,
builder: (ctx, w) {
return Transform.rotate(
angle: degreeToRadians(ctrl.value),
child: wheelContainer,
);
},
),
Container(
width: wheelSize,
height: wheelSize / 2,
margin: const EdgeInsets.only(top: 30),
child: Center(
child: Padding(
padding: EdgeInsets.only(top: this.longNeedleHeight + 10),
child: Image(
image: NetworkImage(
'https://d20nqim3b55fln.cloudfront.net/images/ic_needle_light.png'),
),
),
),
),
Container(
width: wheelSize,
height: wheelSize,
child: CustomPaint(
painter: WheelDecoration(context),
),
),
],
),
);