mcpField
L
lightweight-flutter-animations

lightweight-flutter-animations

github.com/rodydavis開発6075 回インストール2 週間前に更新
リポジトリ

lightweight-flutter-animations について

tickerを使うAnimationWidgetでStateの基底クラスを置き換える、Flutterのアニメーション手法です。CustomPainterによる描画例と、setStateを呼ばずに再ビルドする方法を示します。

主な機能

  1. 01tickerベースのアニメーションウィジェット
  2. 02経過時間と差分時間の追跡
  3. 03レイアウト制約へのアクセス
  4. 04CustomPainterのキャンバス例

活用シーン

  1. 01ticker駆動アニメーションの実装
  2. 02キャンバス上のアニメーション描画

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/rodydavis/skills --skill lightweight-flutter-animations

インストール後、Claude Code で/lightweight-flutter-animationsを入力して読み込まれたか確認します。

詳細

軽量な Flutter アニメーション

概要

まず、抽象クラスを作成します。

abstract class AnimationWidget<T extends StatefulWidget> extends State<T>
    with SingleTickerProviderStateMixin {
  Duration elapsed = Duration.zero;
  Duration delta = Duration.zero;
  late final Ticker ticker;
  BoxConstraints constraints = const BoxConstraints.tightFor();

  @override
  void initState() {
    super.initState();
    ticker = createTicker((elapsed) {
      delta = elapsed - this.elapsed;
      this.elapsed = elapsed;
      update(elapsed);
      if (mounted) setState(() {});
    });
    ticker.start();
    WidgetsBinding.instance.addPostFrameCallback(start);
  }

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

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, dimens) {
      constraints = dimens;
      return paint(context, dimens);
    });
  }

  void start(Duration time) {}

  void update(Duration time);

  Widget paint(BuildContext context, BoxConstraints constraints);
}

これにより、State を AnimationWidget に置き換え、UI を再構築するために setState を呼び出す必要がなくなります。

例

この例では、インラインのキャンバスペインターが必要です。

class InlinePainter extends CustomPainter {
  InlinePainter({
    required this.draw,
    super.repaint,
  });

  final void Function(Canvas canvas, Size size) draw;

  @override
  void paint(Canvas canvas, Size size) {
    draw(canvas, size);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}

新しいウィジェットクラスを使った例です。

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

class SimpleExample extends StatefulWidget {
  const SimpleExample({Key? key}) : super(key: key);

  @override
  State<SimpleExample> createState() => _SimpleExampleState();
}

class _SimpleExampleState extends AnimationWidget<SimpleExample> {
  var x = 0.0;
  var y = 0.0;
  var z = 0.0;

  @override
  void update(Duration time) {
    final t = delta.inMilliseconds / 1000;
    x += t;
    y += t;
    z += t;
  }

  @override
  Widget paint(BuildContext context, BoxConstraints constraints) {
    return Material(
      child: Center(
        child: Container(
          width: 100,
          height: 100,
          transform: Matrix4.identity()
            ..rotateX(x)
            ..rotateY(y)
            ..rotateZ(z),
          child: const Text(
            'Hello World',
            style: TextStyle(
              fontSize: 30,
              fontWeight: FontWeight.bold,
            ),
          ),
        ),
      ),
    );
  }
}

デモ

コメント