View Transitions によるリスト並び替えアニメーション
データのソート・フィルタ・シャッフル時にリストアイテムを新しい位置へなめらかにアニメーション。React Spring/Framer Motion の FLIP レイヤーを完全に置き換える。
詳細な説明
FLIP を無料で
View Transitions API 以前、リスト並び替えのアニメーションには FLIP(First, Last, Invert, Play)が必要でした。古い位置を測定 → DOM を変更 → 新しい位置を測定 → 逆変換を適用 → identity へアニメーション。Framer Motion の <AnimatePresence layout> などのライブラリがこれを自動化していましたが、メガバイト単位の JavaScript を抱える羽目になります。
View Transitions では、各アイテムに固有の名前を付けるだけで十分です:
.todo-item {
view-transition-name: var(--item-name);
}
{todos.map(t => (
<li key={t.id} style={{'--item-name': `todo-${t.id}`}}>{t.text}</li>
))}
function sortTodos() {
document.startViewTransition(() => {
setTodos([...todos].sort((a, b) => a.priority - b.priority));
});
}
ブラウザはソート前に named 要素の位置を全てキャプチャし、React のコミット後に再キャプチャ、各要素を行き先までアニメーションします。
入退場アニメーションの追加
追加 または 削除 されるアイテムには、ブラウザがデフォルトのクロスフェードにフォールバックします。上書きするには:
::view-transition-new(.todo-item) {
animation: 250ms ease-out both fade-in-up;
}
ネストしたトランジション
リストがトランジションするルート内にある場合、外側のルートトランジションが内側のアイテムトランジションを内包します。このネストは自動的に処理され、手動の協調は不要です。
エッジケース:長いリスト
100以上のアイテムを持つリストでは全部に名前を付けると 100以上のスナップショットグループが生成されます。IntersectionObserver で可視性をトグルし、ビューポート内のアイテムだけ に view-transition-name を付けることを検討してください。
ユースケース
ソート可能なリストを持つ Todo アプリ、カードを並び替えるカンバンボード、順位を更新するリーダーボード、再ソートする検索結果、ユーザー入力に応じて行順序が変わるデータテーブル全般。