【问题标题】:How to rotate an image using Flutter AnimationController and Transform?如何使用 Flutter AnimationController 和 Transform 旋转图像?
【发布时间】:2019-05-13 16:58:12
【问题描述】:

我有星星 png 图像,我需要使用 Flutter AnimationController 和 Transformer 旋转星星。我找不到任何图像旋转动画的文档或示例。

知道如何使用 Flutter AnimationController 和 Transform 旋转图像吗?

更新:

class _MyHomePageState extends State<MyHomePage>  with TickerProviderStateMixin {

  AnimationController animationController;

  @override
  void initState() {
    super.initState();
    animationController = new AnimationController(
      vsync: this,
      duration: new Duration(milliseconds: 5000),
    );
    animationController.forward();
    animationController.addListener(() {
      setState(() {
        if (animationController.status == AnimationStatus.completed) {
          animationController.repeat();
        }
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Container(
      alignment: Alignment.center,
      color: Colors.white,
      child: new AnimatedBuilder(
        animation: animationController,
        child: new Container(
          height: 80.0,
          width: 80.0,
          child: new Image.asset('images/StarLogo.png'),
        ),
        builder: (BuildContext context, Widget _widget) {
          return new Transform.rotate(
            angle: animationController.value,
            child: _widget,
          );
        },
      ),
    );
  }
}

【问题讨论】:

  • 你能通过animationRotate初始化的代码吗?
  • 我更新了我的代码。问题是它永远不会旋转 360 度。它旋转了大约 200 圈,然后重新开始,我可以看到它重新绘制了一个间隙。旋转 360 度时遇到问题,当停止时我需要立即重复,以便继续旋转变白停止...
  • 更新了答案

标签: flutter dart flutter-layout transform flutter-animation


【解决方案1】:

完整示例(null 安全):

按“开始”使星形图标旋转,直到您按“停止”。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    _controller = AnimationController(
      duration: const Duration(milliseconds: 5000),
      vsync: this,
    );
    super.initState();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Demo"),
      ),
      body: Center(
        child: Column(
          children: <Widget>[
            RotationTransition(
              turns: Tween(begin: 0.0, end: 1.0).animate(_controller),
              child: Icon(Icons.stars),
            ),
            ElevatedButton(
              child: Text("go"),
              onPressed: () => _controller.forward(),
            ),
            ElevatedButton(
              child: Text("reset"),
              onPressed: () => _controller.reset(),
            ),
          ],
        ),
      ),
    );
  }
}

分步指南:

首先,让您的小部件状态类实现SingleTickerProviderStateMixin

其次,定义一个AnimationController 并且不要忘记处理它。如果您尚未使用 null-safe,请删除 late 关键字。

late AnimationController _controller;

@override
void initState() {
  _controller = AnimationController(
    duration: const Duration(milliseconds: 5000),
    vsync: this,
  );
  super.initState();
}

@override
void dispose() {
  _controller.dispose();
  super.dispose();
}

然后用RotationTransition 包裹你的Widget

RotationTransition(
  turns: Tween(begin: 0.0, end: 1.0).animate(_controller),
  child: Icon(Icons.stars),
),

最后,调用AnimationController 上的方法来启动/停止动画。

  • 运行一次动画,使用.forward
  • 循环动画,使用.repeat
  • 立即停止,使用.stop
  • 停止并将其设置回原来的旋转,使用.reset
  • 停止并为旋转值设置动画,使用.animateTo

【讨论】:

    【解决方案2】:

    这是我的旋转图像示例。我不知道 - 但也许它适合你

    AnimationController rotationController;
    
    @override
    void initState() {
      rotationController = AnimationController(duration: const Duration(milliseconds: 500), vsync: this);
      super.initState();
    }
    //...
    RotationTransition(
      turns: Tween(begin: 0.0, end: 1.0).animate(rotationController),
      child: ImgButton(...)
    //...
    rotationController.forward(from: 0.0); // it starts the animation
    

    UPD - 如何解决Transform.rotate的问题

    在您的情况下,一切都与您编写的完全一样 - 它将图像从 0.0 旋转到 1.0(它是 AnimationController 的默认参数)。对于整圈,您必须将上参数设置为 2 * pi(来自 math 包)

    import 'dart:math';
    //...
    animationController = AnimationController(vsync: this, duration: Duration(seconds: 5), upperBound: pi * 2);
    

    【讨论】:

    【解决方案3】:

    屏幕截图(Null Safe)


    完整代码:

    import 'dart:math' as math;
    
    class _FooPageState extends State<FooPage> with SingleTickerProviderStateMixin{
      late final AnimationController _controller = AnimationController(vsync: this, duration: Duration(seconds: 2))..repeat();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: AnimatedBuilder(
              animation: _controller,
              builder: (_, child) {
                return Transform.rotate(
                  angle: _controller.value * 2 * math.pi,
                  child: child,
                );
              },
              child: FlutterLogo(size: 200),
            ),
          ),
        );
      }
    }
    

    【讨论】:

    • 如何沿 Y 轴旋转,有什么想法吗?
    【解决方案4】:

    在这里我一次旋转 3 张图像...保存在 assets 文件夹中的图像...如果您愿意,您也可以使用网络图像...我在这里以 3 种速度旋转 3 张图像...

    import 'package:flutter/material.dart';
    import 'package:fynd/services/auth.dart';
    import 'dart:async';
    import 'package:fynd/services/cons.dart';
    
    class SplashScreen extends StatefulWidget {
      _SplashScreen createState() => new _SplashScreen();
    }
    
    class _SplashScreen extends State<StatefulWidget>
        with SingleTickerProviderStateMixin {
      AnimationController animationController;
    
      @override
      void initState() {
        super.initState();
        animationController = new AnimationController(
          vsync: this,
          duration: new Duration(seconds: 5),
        );
    
        animationController.repeat();
      }
    
      @override
      Widget build(BuildContext context) {
    
        return new Container(
          alignment: Alignment.center,
          color: Colors.white,
          child: new AnimatedBuilder(
            animation: animationController,
            child: new Container(
              decoration: BoxDecoration(
                  image: DecorationImage(
                      image: AssetImage('assets/images/splash_circle3.png'))),
              child: new AnimatedBuilder(
                animation: animationController,
                child: new Container(
                  decoration: BoxDecoration(
                      image: DecorationImage(
                          image: AssetImage('assets/images/splash_circle2.png'))),
                  child: new AnimatedBuilder(
                      animation: animationController,
                      child: Container(
                          child: Container(
                        decoration: BoxDecoration(
                            image: DecorationImage(
                                image: AssetImage(
                                    'assets/images/splash_circle1.png'))),
                      )),
                      builder: (BuildContext context, Widget _widget) {
                        return new Transform.rotate(
                          angle: animationController.value * 4,
                          child: _widget,
                        );
                      }),
                ),
                builder: (BuildContext context, Widget _widget) {
                  return new Transform.rotate(
                    angle: animationController.value * 5,
                    child: _widget,
                  );
                },
              ),
            ),
            builder: (BuildContext context, Widget _widget) {
              return new Transform.rotate(
                angle: animationController.value * 6,
                child: _widget,
              );
            },
          ),
        );
      }
    }
    

    【讨论】:

      【解决方案5】:

      在这里,我将动画生成器放在 Stack 中。然后你可以动画图像向右(顺时针)旋转和向左(逆时针)旋转。

      import 'package:flutter/material.dart';
      import 'package:fynd/services/auth.dart';
      import 'dart:async';
      import 'package:fynd/services/cons.dart';
      
      class SplashScreen extends StatefulWidget {
        _SplashScreen createState() => new _SplashScreen();
      }
      
      class _SplashScreen extends State<StatefulWidget>
          with SingleTickerProviderStateMixin {
        AnimationController animationController;
      
        @override
        void initState() {
          super.initState();
          animationController = new AnimationController(
            vsync: this,
            duration: new Duration(seconds: 5),
          );
      
          animationController.repeat();
      
        }
      
        @override
        Widget build(BuildContext context)
      
          return new Container(
            alignment: Alignment.center,
            color: Colors.white,
      
            child: new Stack(children: <Widget>[
      
              new AnimatedBuilder(
                animation: animationController,
                child :Container(
                  decoration: BoxDecoration(
                      image: DecorationImage(image: AssetImage('assets/images/splash_circle3.png'),fit: BoxFit.cover)),
      
                ),
                builder: (BuildContext context, Widget _widget) {
                  return new Transform.rotate(
                    angle: animationController.value * 10,
                    child: _widget,
                  );
                },
              ),
      
             new AnimatedBuilder(
              animation: animationController,
              child: Container(
                decoration: BoxDecoration(
                    image: DecorationImage(image: AssetImage('assets/images/splash_circle2.png'),fit: BoxFit.cover)),
      
              ),
              builder: (BuildContext context, Widget _widget) {
                return new Transform.rotate(
                  angle: -animationController.value * 10,
                  child: _widget,
                );
              },
             ),
      
              new AnimatedBuilder(
                  animation: animationController,
                 child: Container(
                    decoration: BoxDecoration(
                        image: DecorationImage(image: AssetImage('assets/images/splash_circle1.png'), fit: BoxFit.cover)),
                  ),
                  builder: (BuildContext context, Widget _widget) {
                    return new Transform.rotate(
                      angle: animationController.value * 10,
                      child: _widget,
                    );
                  }),
      
            ],),
          );
        }
      }
      

      【讨论】:

        【解决方案6】:
        class _MyHomePageState extends State<MyHomePage>  with TickerProviderStateMixin {
        
          AnimationController animationController;
        
          @override
          void initState() {
            super.initState();
            animationController = new AnimationController(
              vsync: this,
              duration: new Duration(milliseconds: 5000),
            );
            animationController.repeat();
        
          }
        
          @override
          Widget build(BuildContext context) {
            return new Container(
              alignment: Alignment.center,
              color: Colors.white,
              child: RotationTransition(
                      child: Icon(Icons.refresh),
                      turns: controller,
                    )
            );
          }
        }
        

        【讨论】:

          【解决方案7】:
          _controller = AnimationController(duration: const Duration(seconds: 3), vsync: this); _animation = Tween(开始:0.0,结束:250.0).animate(_controller) ..addListener(() { setState(() {}); }) ..addStatusListener((状态){ if (state == AnimationStatus.completed) { 打印(“完成”); } }); _controller.forward(); 新的 Future.delayed( const 持续时间(秒:5), () => 导航器.push( 语境, MaterialPageRoute(builder: (context) => SignScreen()), ));

          【讨论】:

            【解决方案8】:

            完整示例只需调用 ImageAnimateRotate(你的小部件)

            class ImageAnimateRotate extends StatefulWidget {
              final Widget child;
              const ImageAnimateRotate({Key? key, required this.child}) : super(key: key);
            
              @override
              _ImageAnimateRotateState createState() => _ImageAnimateRotateState();
            }
            
            class _ImageAnimateRotateState extends State<ImageAnimateRotate> with SingleTickerProviderStateMixin {
              late final AnimationController _controller;
            
              @override
              void initState() {
                super.initState();
                _controller = AnimationController(vsync: this, duration: Duration(seconds: 20))..repeat();
              }
            
              @override
              Widget build(BuildContext context) {
                return Center(
                  child: AnimatedBuilder(
                    animation: _controller,
                    builder: (_, child) {
                      return Transform.rotate(
                        angle: _controller.value * 2 * math.pi,
                        child: child,
                      );
                    },
                    child: widget.child,
                  ),
                );
              }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-08-31
              • 2020-04-21
              • 2011-12-19
              • 2017-04-26
              • 2023-01-14
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多