ほぞぼそと作ってるマグロのゲーム、
ボタンの動きをゲームっぽくしたくて、
いろいろ調べたときの備忘録(*´ω`*)
動きとしてはこんな感じで、ピョコンとなる感じ
ちょっとはゲームっぽい動きのボタンになった(*´ω`*) pic.twitter.com/zsQinyJzj1
— きらぷか@スプシAPI化&積読のサービス運営中🔥 (@kira_puka) May 26, 2024
やりかた
できたのはこんな感じ。このあたりを使って実装するっぽい
- AnimatedBuilder class - widgets library - Dart API
- アニメーションさせるWidget
- AnimationController class - animation library - Dart API
- アニメーションの時間経過をコントロールするクラス
- Tween class - animation library - Dart API
- 実際のアニメーション
- TickerFuture class - scheduler library - Dart API
- 進行中のアニメーションのTicker
import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; class GameButtonWrapper extends HookConsumerWidget { const GameButtonWrapper({ super.key, required this.child, required this.onPressed, }); // ボタンのWidget final Widget child; // クリック時の処理 final Function()? onPressed; @override Widget build(BuildContext context, WidgetRef ref) { TickerFuture? downTicker; // AnimationControllerの準備 final animController = useAnimationController( duration: const Duration(milliseconds: 100), ); // Tweenアニメーションの準備 final pressAnim = Tween<double>(begin: 0.0, end: 1.0).animate( CurvedAnimation(parent: animController, curve: Curves.easeInOut), ); // RepaintBoundaryで再描画範囲を制限 return RepaintBoundary( child: GestureDetector( // tap downしたときにアニメーションを開始 // 実行中のTickerFutureを保持しておく // onPressedはまだ呼ばない onTapDown: (_) { if (onPressed == null) return; downTicker = animController.animateTo(1.0); }, // tap upしたときに、 // tap downのアニメーションが終了するまで待って、 // アニメーションを逆再生し、 // 逆再生が終わったら、onPressedを呼ぶ onTapUp: (_) { if (onPressed == null) return; downTicker?.whenComplete(() { animController.animateTo(0.0).whenCompleteOrCancel(() { onPressed?.call(); }); }); }, // キャンセルされたときは、resetする onTapCancel: () { if (onPressed == null) return; animController.reset(); }, // 実際のアニメーションするWidget部分 child: AnimatedBuilder( animation: pressAnim, builder: (context, child) { // Transform.translateを使って、 // 経過時間分、下にずらす return Transform.translate( offset: Offset(0.0, pressAnim.value * 10), child: child, ); }, child: child, ), ), ); } }
AnimatedBuilder
やAnimationController
の例はあるけど、
それだけだと、いい感じにクリック動作(onPressed
)が実行されない...
TickerFuture
を使って、アニメーションを待つのがポイントっぽい
downTicker?.whenComplete(() { animController.animateTo(0.0).whenCompleteOrCancel(() { onPressed?.call(); }); });
以上!! Flutterでもゲームっぽくできるようになったぞ(*´ω`*)