如何在颤动中应用平移和旋转动画以创建“卡在周围”效果

问题描述 投票:2回答:2

我正在创建n UNO游戏应用程序,这是介绍屏幕部分。我需要一种非常自定义的动画,而我对颤动的自定义动画没有太多的了解。

这里是一些预览

enter image description here

现在,我要创建一个“纸牌飞来飞去”的动画。基本上是卡片(带有svg资产的容器)在屏幕上同时翻译和旋转以创建飞行卡片效果。此动画将一遍又一遍地重复。

我设法制作了一个非常基本的版本,可以平移,不会旋转,看上去也不是那么漂亮。这是代码。

INTROSCREEN

class IntroScreen extends StatefulWidget {
  @override
  _IntroScreenState createState() => _IntroScreenState();
}

class _IntroScreenState extends State<IntroScreen>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation _animation;

  @override
  void initState() {
    _controller =
        AnimationController(vsync: this, duration: Duration(seconds: 4));
    _animation = RainbowColorTween([
      CardColors.COLOR1,
      CardColors.COLOR2,
      CardColors.COLOR3,
      CardColors.COLOR4,
      CardColors.COLOR1,
    ]).chain(CurveTween(curve: Curves.easeInOut)).animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    _controller.repeat();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Container(
          color: _animation.value,
          child: ChangeNotifierProvider<_DataModel>(
            create: (context) => _DataModel(),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                SizedBox(
                  height: 100,
                ),
                _Logo(),
                SizedBox(
                  height: 50,
                ),
                _TextField(),
                _SelectCards(),
                _Play(),
                Expanded(child: FlyingCards(MediaQuery.of(context).size.width)),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class _Logo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 200,
      child: FlareActor(
        "assets/intro_anim.flr",
        alignment: Alignment.center,
        fit: BoxFit.contain,
        animation: 'intro',
      ),
    );
  }
}

这是我设法建立的

class FlyingCards extends StatefulWidget {
  final double width;
  FlyingCards(this.width);
  @override
  _FlyingCardsState createState() => _FlyingCardsState();
}

class _FlyingCardsState extends State<FlyingCards>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation _animation;

  @override
  void initState() {
    _controller =
        AnimationController(vsync: this, duration: Duration(seconds: 2));

    _animation = Tween<double>(begin: 0, end: widget.width)
        .chain(CurveTween(curve: Curves.ease))
        .animate(_controller)
          ..addListener(() {
            setState(() {});
          })
          ..addStatusListener((status) {
            if (status == AnimationStatus.dismissed)
              _controller.forward();
            else if (status == AnimationStatus.completed) _controller.reverse();
          });

    _controller.forward();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: Transform.translate(
        offset: Offset(_animation.value, 0),
        child: Container(
          height: 50,
          width: 50,
          child: SvgPicture.asset('assets/plus4.svg'),
          decoration: BoxDecoration(borderRadius: BorderRadius.circular(20)),
        ),
      ),
    );
  }
}

在上图中,卡实际上是在设备的宽度上来回移动。

我觉得我创建的是制作动画的繁琐方法。如果仍然没有人理解飞行卡动画的含义,愤怒的小鸟游戏屏幕上会出现同样的效果,只是飞来飞去的鸟和猪。我需要同样的东西,但要带我的卡。

[请签出this video并跳至0:22,以获取有关我希望使用的UI的简短参考。

我试图尽可能降低复杂性。感谢您的宝贵时间!

flutter dart flutter-animation
2个回答
1
投票

这里是一个可以扩展的简单示例。“ Hello world!”文本正在平移和旋转。

import 'package:flutter/material.dart';
import 'dart:math';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyAnim(),
        ),
      ),
    );
  }
}

class MyAnim extends StatefulWidget {
  @override
  State<MyAnim> createState() => MyAnimState();
}

class MyAnimState extends State<MyAnim> with SingleTickerProviderStateMixin {
  AnimationController control;

  Animation<double> rot;
  Animation<double> trasl;

  @override
  void initState() {
    super.initState();

    control = AnimationController(
      duration: Duration(seconds: 5),
      vsync: this,
    );

    rot = Tween<double>(
      begin: 0,
      end: 2 * pi,
    ).animate(control);

    trasl = Tween<double>(
      begin: 0,
      end: 300,
    ).animate(control);

    control.repeat();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
        animation: control,
        builder: (_, child) => Stack(children: <Widget>[
              Positioned(
                top: 100,
                left: trasl.value,
                child: Transform(
                  transform: Matrix4.rotationZ(rot.value),
                  alignment: Alignment.center,
                  child: Text('Hello, World!',
                      style: Theme.of(context).textTheme.headline4),
                ),
              ),
            ]));
  }
}

0
投票

我还发布了另一种方法来执行相同的任务,这对许多人来说将更加容易。但是,我不会将其标记为可接受的答案,因为以前的答案是真正的答案。

首先,我们需要添加耀斑依赖。耀斑就像扑扑一样。基本上,它可以帮助我们以60fps或更高的速度播放预制的矢量动画

dependencies:
  flutter:
  flare_flutter: ^2.0.3

现在转到rive,然后创建您喜欢的任何动画。您可以添加矢量和您自己的资源并创建动画。我只是用插画家做了一些卡片。您可以看到我的卡片飞行动画here

完成后,只需以二进制格式导出动画。该文件将具有.flr格式。

现在从资产文件夹应用动画。

import 'package:flare_flutter/flare_actor.dart';
return Container(
      height: 200,
      width: MediaQuery.of(context).size.width,
      child: FlareActor(
        "assets/cards_flying.flr",
        alignment: Alignment.center,
        fit: BoxFit.fill,
        animation: 'cards',
      ),
    );

我希望它在某种程度上有用。我觉得值得一提。

© www.soinside.com 2019 - 2024. All rights reserved.