Dart 飞镖颤振:如何绕圆圈旋转?

Dart 飞镖颤振:如何绕圆圈旋转?,dart,flutter,Dart,Flutter,如何让正方形对手势检测器做出响应 围绕一个圆旋转正方形。顺时针转动它应该会 从0到360的正增长和逆时针方向的负增长应从 360比0。但在这里,它增加到超过360,也低于0 负值。对阻力的反应是不可预测的 只有在检测到手势而不是圆时,正方形才应该旋转 在它后面 我不知道这是否是解决问题的方法。任何帮助都是非常有用的 非常感谢。我已经干了好几天了 import 'dart:math'; import 'package:flutter/material.dart'; import 'package:

如何让正方形对手势检测器做出响应 围绕一个圆旋转正方形。顺时针转动它应该会 从0到360的正增长和逆时针方向的负增长应从 360比0。但在这里,它增加到超过360,也低于0 负值。对阻力的反应是不可预测的

只有在检测到手势而不是圆时,正方形才应该旋转 在它后面

我不知道这是否是解决问题的方法。任何帮助都是非常有用的 非常感谢。我已经干了好几天了

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),
        ),
      ),
    ],
  ),
);