Animation 在颤振动画中更新动画值的正确方法是什么?

Animation 在颤振动画中更新动画值的正确方法是什么?,animation,dart,flutter,flutter-animation,Animation,Dart,Flutter,Flutter Animation,所以我尝试在flifter中创建一个动画,每次用户按下一个按钮时需要不同的结果 我已经根据实现了以下代码,并创建了一个函数来更新它 class _RoulettePageWidgetState extends State<RoulettePageWidget> with SingleTickerProviderStateMixin { Animation<double> _animation; Tween<double> _tween; An

所以我尝试在flifter中创建一个动画,每次用户按下一个按钮时需要不同的结果

我已经根据实现了以下代码,并创建了一个函数来更新它

class _RoulettePageWidgetState extends State<RoulettePageWidget>
with SingleTickerProviderStateMixin {
   Animation<double> _animation;
   Tween<double> _tween;
   AnimationController _animationController;

   int position = 0;

   @override
   void initState() {
      super.initState();
      _animationController =
          AnimationController(duration: Duration(seconds: 2), vsync: this);
      _tween = Tween(begin: 0.0, end: 100.0);
      _animation = _tween.animate(_animationController)
          ..addListener(() {
              setState(() {});
          });
   }

   void setNewPosition(int newPosition) {
      _tween = Tween(
        begin: 0.0,
        end: math.pi*2/25*newPosition);
      _animationController.reset();
      _tween.animate(_animationController);
      _animationController.forward();
   }

   @override
   Widget build(BuildContext context) {
      return Container(
         child: Column(
            children: <Widget>[
               Center(
                  child: Transform.rotate(
                     angle: _animationController.value,
                     child: Icon(
                        Icons.arrow_upward,
                     size: 250.0,
                  ),
               )),
               Expanded(
                  child: Container(),
               ),
               RaisedButton(
                  child: Text('SPIN'),
                  onPressed: () {
                     setState(() {
                        setNewPosition(math.Random().nextInt(25));
                     });
                  },
               )
            ],
         )
      );
   }
}
class\u RoulettePageWidgetState扩展状态
使用SingleTickerProviderStateMixin{
动画(动画),;
吐温;
AnimationController _AnimationController;
int位置=0;
@凌驾
void initState(){
super.initState();
_动画控制器=
AnimationController(持续时间:持续时间(秒数:2),vsync:this);
_吐温=吐温(开始:0.0,结束:100.0);
_动画=_tween.animate(_animationController)
…addListener(){
setState((){});
});
}
void setNewPosition(int newPosition){
_吐温(
开始:0.0,
结束:数学pi*2/25*newPosition);
_animationController.reset();
_动画制作(_animationController);
_animationController.forward();
}
@凌驾
小部件构建(构建上下文){
返回容器(
子:列(
儿童:[
居中(
子对象:Transform.rotate(
角度:_animationController.value,
子:图标(
图标。向上箭头,
尺寸:250.0,
),
)),
扩大(
子级:容器(),
),
升起的按钮(
子项:文本('SPIN'),
已按下:(){
设置状态(){
setNewPosition(math.Random().nextInt(25));
});
},
)
],
)
);
}
}
如您所见,我正在更新
之间的
开始:
结束:
,但这似乎并没有改变动画

那么,每次用户按下按钮时,我应该如何创建“不同”的动画呢

总体思路是使动画以随机新值彼此构建,例如:

  • 第一次旋转:0->10
  • 第二圈:10->13
  • 第三圈:13->18
  • 。。。等
所以我想知道我是否可以更新动画,还是应该每次都创建一个新的动画? 我能想到的另一件事是跟踪位置,每次(0.0->100.0)都使用相同的动画作为传输的百分比

因此,与其从10->15创建新动画,我将做如下操作:
currentValue=10+(15-10)/100*\u animationController.value

我将略过你的代码,集中讨论你真正想问的问题:

总体思路是使动画以随机新值彼此构建,例如:

  • 第一次旋转:0->10

  • 第二圈:10->13

  • 第三圈:13->18

  • 。。。等

对于这样的显式动画,有三个对象是您感兴趣的:

  • 控制器,这是一种特殊类型的动画,仅从其下限到上限线性生成值(双倍,通常为0.0和1.0)。您可以控制动画的流程-向前发送、反转、停止或重置动画

  • 这不是一个动画,而是一个动画。tween定义了两个值之间的插值,这两个值甚至不必是数字。它在引擎盖下实现了一个
    transform
    方法,该方法接收动画的当前值,并输出您想要处理的实际值:另一个数字、一种颜色、一个线性渐变,甚至是一个完整的小部件。这是你应该用来生成旋转角度的

  • 一个动画,这是一个你实际要使用其值的动画(因此,这是你获取要使用的值的地方)。你可以通过给你的孩子一个要变换的父动画来实现这一点——这可能是你的控制器,但也可以是你在其上构建的其他类型的动画(比如曲线动画,它可以给你缓和或弹性/弹性曲线等等)。颤振的动画是高度可组合的方式

您的代码之所以失败,主要是因为您实际上没有使用在构建方法中创建的顶级动画,并且每次调用
setNewPosition
时都在创建一个新的tween和动画。您可以对多个动画“循环”使用相同的tween和动画-只需更改现有tween的
begin
end
属性,它就会在动画中出现气泡。结果是这样的:

class _RoulettePageWidgetState extends State<RoulettePageWidget>
with SingleTickerProviderStateMixin {
   Animation<double> _animation;
   Tween<double> _tween;
   AnimationController _animationController;
   math.Random _random = math.Random();

   int position = 0;

   double getRandomAngle() {
      return math.pi * 2 / 25 * _random.nextInt(25);
   }

   @override
   void initState() {
      super.initState();
      _animationController =
          AnimationController(duration: Duration(seconds: 2), vsync: this);
      _tween = Tween(begin: 0.0, end: getRandomAngle());
      _animation = _tween.animate(_animationController)
          ..addListener(() {
              setState(() {});
          });
   }

   void setNewPosition() {
      _tween.begin = _tween.end;
      _animationController.reset();
      _tween.end = getRandomAngle();
      _animationController.forward();
   }

   @override
   Widget build(BuildContext context) {
      return Container(
         child: Column(
            children: <Widget>[
               Center(
                  child: Transform.rotate(
                     angle: _animation.value,
                     child: Icon(
                        Icons.arrow_upward,
                     size: 250.0,
                  ),
               )),
               Expanded(
                  child: Container(),
               ),
               RaisedButton(
                  child: Text('SPIN'),
                  onPressed: setNewPosition,
               )
            ],
         )
      );
   }
}
class\u RoulettePageWidgetState扩展状态
使用SingleTickerProviderStateMixin{
动画(动画),;
吐温;
AnimationController _AnimationController;
math.Random _Random=math.Random();
int位置=0;
double getRandomAngle(){
返回math.pi*2/25*_random.nextInt(25);
}
@凌驾
void initState(){
super.initState();
_动画控制器=
AnimationController(持续时间:持续时间(秒数:2),vsync:this);
_tween=tween(开始:0.0,结束:getRandomAngle());
_动画=_tween.animate(_animationController)
…addListener(){
setState((){});
});
}
void setNewPosition(){
_tween.begin=\u tween.end;
_animationController.reset();
_tween.end=getRandomAngle();
_animationController.forward();
}
@凌驾
小部件构建(构建上下文){
返回容器(
子:列(
儿童:[
居中(
子对象:Transform.rotate(
角度:_animation.va
..addListener(() {
  setState(() {});
});
class RotationExample extends StatefulWidget {
  final Widget child;

  const RotationExample({
    Key key,
    this.child,
  }) : super(key: key);

  @override
  RotationExampleState createState() {
    return new RotationExampleState();
  }
}

class RotationExampleState extends State<RotationExample> {
  final _random = math.Random();
  double rad = 0.0;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _rotate,
      child: AnimatedTransform(
        duration: const Duration(seconds: 1),
        alignment: Alignment.center,
        transform: Matrix4.rotationZ(rad),
        child: Container(
          color: Colors.red,
          height: 42.0,
          width: 42.0,
        ),
      ),
    );
  }

  void _rotate() {
    setState(() {
      rad = math.pi * 2 / 25 * _random.nextInt(25);
    });
  }
}
class AnimatedTransform extends ImplicitlyAnimatedWidget {
  final Matrix4 transform;
  final AlignmentGeometry alignment;
  final bool transformHitTests;
  final Offset origin;
  final Widget child;

  const AnimatedTransform({
    Key key,
    @required this.transform,
    @required Duration duration,
    this.alignment,
    this.transformHitTests = true,
    this.origin,
    this.child,
    Curve curve = Curves.linear,
  })  : assert(transform != null),
        assert(duration != null),
        super(
          key: key,
          duration: duration,
          curve: curve,
        );

  @override
  _AnimatedTransformState createState() => _AnimatedTransformState();
}

class _AnimatedTransformState
    extends AnimatedWidgetBaseState<AnimatedTransform> {
  Matrix4Tween _transform;

  @override
  void forEachTween(TweenVisitor<dynamic> visitor) {
    _transform = visitor(_transform, widget.transform,
        (dynamic value) => Matrix4Tween(begin: value));
  }

  @override
  Widget build(BuildContext context) {
    return Transform(
      alignment: widget.alignment,
      transform: _transform.evaluate(animation),
      transformHitTests: widget.transformHitTests,
      origin: widget.origin,
      child: widget.child,
    );
  }
}