【Flutter】カードめくりアニメーションを実装する

もくじ

こんにちは。

スマホアプリをメインに開発しているロッキーカナイです。

最近Flutterでアニメーション動作を入れるのにハマってます。

ということで今回は、Flutterでカードめくりアニメーションを実装してみましたので、紹介したいと思います。

やること

  1. トランプのカードめくりのアニメーションを実装する
  2. デフォルトは裏面、タップすると表を向く。
  3. 表面でタップすると裏を向く

今回はこれだけなので、サクッとコードを紹介します。

コード

import 'package:flutter/material.dart';


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

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

/*
 * カードページ
 */
class CardPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: Center(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[

            /*
             * トランプを並べる
             */
            AnimationCard(
              Image.asset(
                "images/card_j.png",
              ),
            ),

            SizedBox(
              width: 10.0,
            ),

            AnimationCard(
              Image.asset(
                "images/card_q.png",
              ),
            ),

            SizedBox(
              width: 10.0,
            ),

            AnimationCard(
              Image.asset(
                "images/card_k.png",
              ),
            ),
          ],
        ),
      ),
    );
  }
}

/*
 * アニメーショントランプ
 */
class AnimationCard extends StatefulWidget {

  final Image frontImage;

  AnimationCard(this.frontImage) : super();

  _AnimationCardState createState() => _AnimationCardState();
}


/*
 * アニメーショントランプ ステート
 */
class _AnimationCardState extends State<AnimationCard> with TickerProviderStateMixin {

  AnimationController _controller;
  Animation<double> _frontAnination;
  Animation<double> _backAnination;

  Image _backImage = Image.asset("images/card_back.png");

  @override
  void initState() {

    super.initState();

    /*
     * アニメーションコントローラ
     */
    _controller = AnimationController(
      vsync: this,
      duration: Duration(
        milliseconds: 200,
      ),
    );

    /*
     * トランプの表アニメーション
     */
    _frontAnination = Tween(
      begin: 1.0,
      end: 0.0,
    ).animate(
      CurvedAnimation(
        parent: _controller,
        curve: Interval(
          0.0,
          0.5,
          curve: Curves.easeIn,
        ),
      ),
    );

    /*
     * トランプの裏アニメーション
     */
    _backAnination = CurvedAnimation(
      parent: _controller,
      curve: Interval(
        0.5,
        1.0,
        curve: Curves.easeOut,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {

    return SizedBox(
      width: 100.0,
      child: GestureDetector(

        /*
         * トランプタッチジェスチャー
         */
        onTap: (){

          setState(() {
            if (_controller.isCompleted || _controller.velocity > 0)
              _controller.reverse();
            else
              _controller.forward();
          });
        },

        child: Stack(
          children: <Widget>[

            /*
             * トランプ表
             */
            AnimatedBuilder(
              child: widget.frontImage,
              animation: _backAnination,
              builder: (BuildContext context, Widget child) {

                return _getCardTransform(
                  child,
                  _backAnination.value,
                );
              },
            ),

            /*
             * トランプ裏
             */
            AnimatedBuilder(
              child: _backImage,
              animation: _frontAnination,
              builder: (BuildContext context, Widget child) {

                return _getCardTransform(
                  child,
                  _frontAnination.value,
                );
              },
            ),
          ],
        ),
      ),
    );
  }

  Transform _getCardTransform(Widget child, dynamic value) {

    final Matrix4 transform = Matrix4.identity()
      ..scale(value, 1.0, 1.0);

    return Transform(
      transform: transform,
      alignment: FractionalOffset.center,
      child: child,
    );
  }

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

素材はこちらより拝借しました。

プレビュー

よくあるカードめくりのアニメーションが実装できました。

関連する記事

もっと見る