lightweight-flutter-animations について
tickerを使うAnimationWidgetでStateの基底クラスを置き換える、Flutterのアニメーション手法です。CustomPainterによる描画例と、setStateを呼ばずに再ビルドする方法を示します。
主な機能
- 01tickerベースのアニメーションウィジェット
- 02経過時間と差分時間の追跡
- 03レイアウト制約へのアクセス
- 04CustomPainterのキャンバス例
活用シーン
- 01ticker駆動アニメーションの実装
- 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,
),
),
),
),
);
}
}
デモ
コメント
Markdown 対応