飞镖颤动:如何围绕圆圈旋转?

时间:2018-05-29 10:31:10

标签: dart flutter

如何让广场响应手势探测器 围绕一个圆圈旋转方块。顺时针转动它应该给 从0到360的正增加和逆时针应该减少 360到0.但是这里它增加到超过360并且也低于0进入 减去值。对阻力的反应是不可预测的。

只有在IT检测到手势而不是圆圈时,方块才会旋转 背后。

即使这是解决问题的方法,我也不知道。任何帮助都会非常 非常感激。我已经在这几天了。

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()}');
});
}

3 个答案:

答案 0 :(得分:1)

您可以使用fluttery package。它有radial drag gesture detector

      child: new RadialDragGestureDetector(
        onRadialDragStart: _onRadialDragStart,
        onRadialDragUpdate: _onRadialDragUpdate,
        onRadialDragEnd: _onRadialDragEnd,
        child: new ...

并且听众在开始和更新时获得PolarCoord,因此您可以看到弧度。

你没有提及你是做一两个手指手势,所以如果这有帮助,请告诉我

答案 1 :(得分:1)

您可以使用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,);
  }
}

答案 2 :(得分:1)

您可以在panUpdatepanEnd上进行简单的计算:

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

以下是完整的示例供您参考: 密码笔链接:https://codepen.io/godwinvc/pen/oNxrOeX

iframe {
  display:block;
    vertical-align:top;
  width: 600px;
  height: 800px;
  
}
<iframe style="overflow-y: auto; -webkit-overflow-scrolling: touch; display:block; vertical-align:top;" src="https://codepen.io/godwinvc/full/oNxrOeX"></iframe>