---
name: tray_container.aicomponent
description: 底部篮子/托盘 UI 组件。提供 N 格槽位容器，支持同类聚合插入动画、消除动画（放大淡出）、满溢抖动、重新排列。通过 textureKeyFn 回调注入纹理映射，可用于任何需要收集+消除的玩法。
triggers: 需要底部篮子、托盘、收集槽、物品容器 UI 时触发。
---

# 底部篮子/托盘容器（Tray Container）

## 说明

固定在屏幕底部的 N 格槽位容器，用于收集从棋盘进入的物品。支持：

- **同类聚合插入**：新物品自动插到最后一个同色物品旁边
- **消除动画**：匹配成功时物品放大+淡出消失
- **重新排列**：物品增删后自动滑动到正确位置
- **满溢抖动**：篮子满时水平震动反馈

## Scaffold

| 目标路径 | 来源 | 说明 |
|---------|-----|------|
| `src/game/ui/TrayRenderer.ts` | `ref/TrayRenderer.ts` | 完整的篮子渲染器 |

## Recipe

| 决策 | 原因 |
|------|------|
| **三模式统一接口** | Phaser 精灵、HTML CSS、Three.js Mesh 三种实现对 GameScene 暴露相同方法（`addItem`、`rearrangeItems`、`removeMatchedItems`、`shake`），GameScene 无需感知底层模式 |
| **textureKeyFn 回调注入** | 纹理/颜色映射由调用方提供，TrayRenderer 不绑定具体资产；不同 Remix 变体可用不同颜色映射，组件可复用 |
| **同类聚合插入位置** | 新物品插到最后一个同类旁边（非末尾），视觉上更直观地表达"同类靠近"语义，是三消类游戏标准 UX |
| **HTML Overlay 在 Three.js 中** | 3D 项目中 2D UI 用 DOM 比 Three.js Plane Mesh 更简单（CSS transition 动画免费），不占 WebGL 渲染管线 |

## Adapter

- **Role**: `trayContainerRenderer` — 底部 N 格槽位篮子 UI（Phaser/HTML/Three.js 三模式）
- **Provides**: `TrayRenderer`（Phaser 精灵）、`TrayRendererHtmlOverlay`（CSS DOM）、`TrayRenderer3D`（Three.js Mesh）
- **Requires**: `phaser.aicomponent`（Phaser 模式）；`threejs.aicomponent`（3D Mesh 模式）
- **Consumed by**: `game_scene.aicomponent`（持有 trayRenderer 实例）、`slide_out_to_tray_animation.aicomponent`（飞入动画的目标槽位）
- **Integration point**: `src/game/ui/TrayRenderer.ts` → `Game.ts` 初始化后调用 `setup(areaRect, capacity)`

## Imports

- `phaser.aicomponent`（硬依赖：Phaser.Scene, Phaser.GameObjects, Phaser.Tweens）

## 关键接口

```typescript
class TrayRenderer {
  setup(areaRect: Rect, capacity: number): void;
  getSlotWorldPos(index: number): { x: number; y: number };
  addItemSprite(item: TrayItem, index: number): Phaser.GameObjects.Image;
  rearrangeItems(tray: TrayItem[], animate?: boolean): void;
  removeMatchedItems(matchedIds: string[], onComplete: () => void): void;
  shake(): void;
  destroy(): void;
}
```

## 配置参数

| 参数 | 默认 | 说明 |
|------|------|------|
| capacity | 7 | 槽位数量 |
| matchDuration | 300ms | 消除动画时长 |
| rearrangeDuration | 200ms | 重排动画时长 |
| shakeAmount | 8px | 抖动幅度 |

## 集成模式

```typescript
// 初始化
const trayRenderer = new TrayRenderer(scene);
trayRenderer.setup({ x, y, width, height }, 7);

// 物品飞入后
const sprite = trayRenderer.addItemSprite(item, insertIndex);
trayRenderer.rearrangeItems(currentTray, true);

// 匹配消除
trayRenderer.removeMatchedItems(matchedIds, () => {
  trayRenderer.rearrangeItems(newTray, true);
});

// 满溢
trayRenderer.shake();
```

## HTML Overlay 模式（Three.js 推荐）

用 CSS + DOM 实现的篮子，固定在屏幕底部。适用于 Three.js 3D 项目中不需要 3D 深度的 UI 组件。

**优点**：不占用 WebGL 渲染管线 / CSS transition 动画流畅 / 不受 3D 相机变换影响

```typescript
import { TrayRendererHtmlOverlay } from "../ui/TrayRendererHtmlOverlay";

const tray = new TrayRendererHtmlOverlay({
  capacity: 7,
  colorToHex: (color) => CAR_COLOR_CSS_MAP[color],
});
tray.setup("game-container");

// 物品飞入后
tray.addItem(item, insertIndex);
tray.rearrangeItems(currentTray);

// 消除
tray.removeMatchedItems(matchedIds, () => {
  tray.rearrangeItems(newTray);
});
```

## 3D Mesh 模式（完全沉浸式）

在 Three.js 场景内用 3D Mesh 排列表示物品。需要每帧调用 `update(dt)` 驱动动画。

```typescript
import { TrayRenderer3D } from "../ui/TrayRenderer3D";

const tray = new TrayRenderer3D(scene, {
  capacity: 7,
  cellSize: 1.0,
  colorToHex: (color) => CAR_COLOR_HEX_MAP[color],
});
tray.setup(new THREE.Vector3(boardCenterX, 0, boardHeight + 2));

// 每帧更新
onUpdate(dt) { tray.update(dt); }

// 物品飞入后
tray.addItem(item, insertIndex);
tray.rearrangeItems(currentTray);
```

## 模式对比

| 维度 | phaser-sprite | html-overlay | threejs-mesh |
|------|--------------|-------------|-------------|
| 引擎 | Phaser 3 | 任意（DOM） | Three.js |
| 性能 | 好 | 最好 | 中等 |
| 沉浸感 | 2D | 2D（覆盖） | 完全 3D |
| 动画 | Phaser Tween | CSS transition | 手写插值 |
| 复杂度 | 低 | 低 | 中 |
