首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >飞镖扑腾:如何绕圆圈旋转?

飞镖扑腾:如何绕圆圈旋转?
EN

Stack Overflow用户
提问于 2018-05-29 18:31:10
回答 3查看 3.1K关注 0票数 3

如何让正方形响应手势检测器绕圆旋转正方形。顺时针旋转它应该会从0增加到360,逆时针旋转应该从360减少到0。但在这里,它会增加到360以上,也会在0以下变成负值。对拖曳的反应是不可预知的。

只有当它检测到手势而不是后面的圆圈时,方块才会旋转。

我不知道这是否是解决问题的方法。任何帮助都将不胜感激。我做这个已经有几天了。

代码语言:javascript
复制
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()}');
});
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-10-05 02:35:48

你可以在panUpdatepanEnd上通过简单的计算来做到这一点

代码语言:javascript
复制
 _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;
});
}

在平移结束时:

代码语言:javascript
复制
_panEndHandler(DragEndDetails d) {
ctrl
    .animateTo(roundToBase(degree.roundToDouble(), 10),
        duration: Duration(milliseconds: 551), curve: Curves.easeOutBack)
    .whenComplete(() {
  setState(() {
    degree = roundToBase(degree.roundToDouble(), 10);
  });
});
}

然后把它们连接到一个手势检测器上:

代码语言:javascript
复制
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),
        ),
      ),
    ],
  ),
);

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

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

票数 3
EN

Stack Overflow用户

发布于 2018-05-30 09:58:52

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

代码语言:javascript
复制
      child: new RadialDragGestureDetector(
        onRadialDragStart: _onRadialDragStart,
        onRadialDragUpdate: _onRadialDragUpdate,
        onRadialDragEnd: _onRadialDragEnd,
        child: new ...

侦听器在启动和更新时获取PolarCoord,这样您就可以看到弧度。

你没有提到如果你做一个或两个手指手势,所以让我知道这是否有帮助

票数 1
EN

Stack Overflow用户

发布于 2019-10-04 10:58:30

您可以使用onPanUpdate。

代码语言:javascript
复制
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,);
  }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50582134

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档