mcpField
M
maui-animations

maui-animations

github.com/davidortinauデザイン・UI17661 回インストール16 週間前に更新
リポジトリ

maui-animations について

.NET MAUI アプリ開発者向けのアニメーションスキルです。キャンセルや繰り返しの扱い、アクセシビリティ、性能、イージング選択の注意点をまとめています。

主な機能

  1. 01重複アニメーションの防止とキャンセル
  2. 02カスタムアニメーションの繰り返し設定
  3. 03視覚効果を減らす設定への対応
  4. 04並列アニメーションと性能の指針
  5. 05用途に応じたイージング選択

活用シーン

  1. 01短時間に呼び出されたアニメーションの乱れを修正
  2. 02視覚効果を減らしたいユーザーへの対応
  3. 03並列実行する画面アニメーションの計画

インストール

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

$npx skills add https://github.com/davidortinau/maui-skills --skill maui-animations

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

同梱ファイルreferences/animations-api.md

詳細

.NET MAUI アニメーション

よくある間違い

❌ 新しいアニメーションを開始する前にキャンセルし忘れる

同じプロパティで複数のアニメーションを実行すると、視覚的な乱れが生じます。

// ❌ If called rapidly, animations queue and overlap
async void OnButtonClicked()
{
    await view.FadeTo(0, 500);
    await view.FadeTo(1, 500);
}

// ✅ Cancel first, then animate
async void OnButtonClicked()
{
    view.CancelAnimations();
    await view.FadeTo(0, 500);
    await view.FadeTo(1, 500);
}
❌ カスタムアニメーションの繰り返しコールバックに関する誤解

子アニメーションの repeat コールバックから true を返しても、親アニメーションは繰り返されません。親アニメーションの繰り返しを制御するのは、親の Commit に渡す repeat コールバックだけです。

// ❌ This does NOT loop the parent animation
parent.Add(0.0, 1.0, new Animation(v => view.Scale = v, 1, 2));
parent.Commit(view, "MyAnim", length: 1000,
    repeat: () => false);  // Parent won't loop

// ✅ Loop the parent by passing repeat to Commit
parent.Commit(view, "MyAnim", length: 1000,
    repeat: () => true);  // This loops the entire animation
❌ AbortAnimation の名前の不一致

AbortAnimation("name") は、Commit に渡した文字列と完全に一致する必要があります。一致しない場合、何も起こりません。

// ❌ Name mismatch — animation keeps running
parent.Commit(view, name: "MyAnimation", length: 1000);
view.AbortAnimation("myAnimation");  // Wrong case!

// ✅ Use a constant for the name
const string AnimName = "MyAnimation";
parent.Commit(view, name: AnimName, length: 1000);
view.AbortAnimation(AnimName);

アクセシビリティ:モーションの低減に配慮する

アニメーションを実行する前に、必ず IsAnimationEnabled を確認してください。OS の省電力モード/モーション低減モードが有効な場合、この値は false になります。

// ❌ Ignores user's accessibility preference
await view.FadeTo(1, 500);

// ✅ Respects reduced-motion settings
if (view.IsAnimationEnabled)
    await view.FadeTo(1, 500);
else
    view.Opacity = 1;  // Jump to final state instantly

パフォーマンスに関するヒント

  • アニメーションのコールバックは 16ms 未満に保つ — Commit のデフォルト値 rate: 16 は、60fps での 1 フレームに相当します。複雑なコールバックはカクつきの原因になります。
  • レイアウトを引き起こすプロパティ(WidthRequest、HeightRequest)のアニメーションは避ける — 代わりに TranslationX/Y と Scale を使用してください。
  • 並列アニメーションには Task.WhenAll を使用する — await を連鎖させる方法は、より時間がかかります。
// ❌ Sequential — takes 1500ms total
await view.FadeTo(1, 500);
await view.ScaleTo(1.5, 500);
await view.RotateTo(360, 500);

// ✅ Parallel — takes 500ms total
await Task.WhenAll(
    view.FadeTo(1, 500),
    view.ScaleTo(1.5, 500),
    view.RotateTo(360, 500));

イージングの選び方

目的イージング理由
ボタンのフィードバックCubicOutすばやく減速するため、応答性よく感じられます
ページ遷移CubicInOut開始と終了が滑らかです
バウンドする要素BounceOut遊び心があり、目を引きます
バネ効果SpringOut自然で弾力のある動きになります
ローディングインジケーターLinear継続的な動きに適した一定速度です
表示/非表示SinIn / SinOut控えめで、注意をそらしません

コメント