# 机械屏动作编辑器优化方案

## 1. 核心原则

动作和视频解耦：

- 视频只是临时预览素材。
- 动作列表只描述机械屏如何运动。
- 导出的动作配置 JSON 不保存任何视频参数。
- 同一套动作可以配合不同视频使用。

动作 JSON 不包含：

```json
{
  "videoUrl": "",
  "videoName": "",
  "videoDuration": 0,
  "videoWidth": 0,
  "videoHeight": 0,
  "videoPath": ""
}
```

---

## 2. 右侧运动编辑器布局

建议结构：

```text
运动编辑器

[选择] [全选] [清除]

已选中：136 个单元

[预览效果]

运动类型
[同步伸缩]
[横向波浪]
[纵向波浪]

幅度：70
单次时间：2.00 秒
次数：3
总时长：6.00 秒

[增加动作] [保存修改]

动作列表
[新建] [载入] [导出]

▶ 动作 1｜横向波浪｜0.00s - 6.00s｜6.00s [上移] [下移]
  动作 2｜同步伸缩｜6.00s - 8.00s｜2.00s [上移] [下移]
```

---

## 3. 选择模式

点击 **选择** 后进入编辑选择状态：

- 屏幕恢复初始状态。
- 停止动作预览。
- 单元格显示当前选中范围。
- 鼠标滚轮仍可放大缩小。
- 鼠标拖拽不再旋转视角。
- 鼠标点击单元格可选择/取消选择。
- 鼠标拖动可框选单元区域。

### 单元点击逻辑

```text
未选中 → 点击后选中
已选中 → 点击后取消选择
```

### 框选逻辑

建议第一版：框选只增加选择，不做反选。

---

## 4. 运动类型

保留 3 种：

```text
同步伸缩
横向波浪
纵向波浪
```

去掉：

```text
涟漪
```

---

## 5. 参数命名

原参数调整：

| 原名称 | 新名称 | 说明 |
|---|---|---|
| 振幅 | 幅度 | 最大伸出距离 |
| 频率 | 单次时间 | 一次完整动作的时间，单位秒 |
| 速度 | 删除 | 不再使用 |
| 新增 | 次数 | 动作重复次数 |

动作总时间：

```text
总时长 = 单次时间 × 次数
```

所有秒数显示保留 2 位小数：

```text
单次时间：2.00 秒
总时长：6.00 秒
```

---

## 6. 增加动作

按钮文字：

```text
增加动作
```

点击后，将当前面板配置保存为一个新动作：

```js
{
  type: 'wave_h',
  amplitude: 70,
  duration: 2.0,
  repeat: 3,
  targets: ['unit_0_0', 'unit_1_0']
}
```

动作列表显示：

```text
动作 1｜横向波浪｜0.00s - 6.00s｜6.00s
动作 2｜同步伸缩｜6.00s - 8.00s｜2.00s
```

动作开始/结束时间不需要保存，根据列表顺序自动计算。

---

## 7. 修改动作

增加按钮：

```text
保存修改
```

逻辑：

- 点击动作列表中的某个动作。
- 上方面板加载该动作参数。
- 单元格显示该动作选中的单元。
- 修改参数或重新选择单元。
- 点击 **保存修改** 覆盖当前动作。

如果没有选中动作，点击保存修改提示：

```text
请先选择要修改的动作
```

### 增加动作与保存修改的区别

| 按钮 | 行为 |
|---|---|
| 增加动作 | 永远新增动作 |
| 保存修改 | 覆盖当前选中的动作 |

---

## 8. 动作列表操作

每个动作增加：

```text
[上移] [下移]
```

规则：

- 第一项上移按钮禁用。
- 最后一项下移按钮禁用。
- 移动后动作编号根据列表顺序重新生成。
- 当前选中的动作移动后仍保持选中。

后续可扩展：

```text
[复制] [删除] [预览]
```

---

## 9. 动作列表管理

增加：

```text
[新建] [载入] [导出]
```

### 新建动作列表

作用：清空当前动作列表。

点击后建议确认：

```text
确定要新建动作列表吗？当前动作会被清空。
```

确认后：

- 清空动作列表。
- 清空当前选中动作。
- 清空单元选择。
- 屏幕恢复初始状态。

### 载入动作列表

从本地 JSON 文件载入动作列表。

载入后：

- 恢复动作数组。
- 重新渲染动作列表。
- 不自动加载视频。
- 视频仍由用户另行选择。

### 导出动作列表

导出 JSON 文件，不包含视频参数。

建议文件结构：

```json
{
  "version": "1.0",
  "name": "开场动作",
  "display": {
    "columns": 34,
    "rows": 4,
    "unitSize": 50,
    "thickness": 60
  },
  "actions": [
    {
      "type": "wave_h",
      "amplitude": 70,
      "duration": 2.0,
      "repeat": 3,
      "targets": [
        "unit_0_0",
        "unit_1_0"
      ]
    }
  ]
}
```

---

## 10. 预览效果

增加按钮：

```text
预览效果
```

点击后预览当前面板配置：

- 当前选中的单元。
- 当前运动类型。
- 当前幅度。
- 当前单次时间。
- 当前次数。

预览总时间：

```text
单次时间 × 次数
```

预览结束后：

- 自动停止动作。
- 屏幕恢复初始状态。
- 保留单元选择。
- 回到编辑选择状态。

点击 **选择** 时：

- 立即停止预览。
- 恢复编辑状态。

---

## 11. 视频时间轴

载入视频后，底部增加视频时间轴。

时间轴显示：

- 当前视频时间。
- 视频总时长。
- 动作列表对应的动作块。
- 当前动作高亮。
- 当前播放指针。

示例：

```text
0.00s | 动作1 | 动作2 | 动作3 | 空白 | 20.00s
```

动作块根据动作总时长占比例显示。

---

## 12. 时间轴与动作同步

拖动时间轴时间点时：

- 视频跳转到对应时间。
- 机械屏显示该时间点的动作状态。
- 动作列表高亮当前动作。
- 右侧面板加载当前动作参数。
- 单元格显示当前动作选中的单元。

如果拖动到没有动作的时间：

- 动作列表不高亮。
- 屏幕恢复初始状态。
- 面板不强制覆盖。

### 播放时同步

视频自然播放时：

- 时间轴指针移动。
- 机械屏跟随动作运动。
- 动作列表高亮当前动作。
- 不强制覆盖右侧正在编辑的参数。

只有用户手动拖动时间轴时，才自动加载动作到右侧面板。

---

## 13. 视频长度与动作长度提示

动作总时长小于视频时长：

```text
动作总时长 8.00 秒，视频时长 20.00 秒，后面 12.00 秒无动作
```

动作总时长大于视频时长：

```text
动作总时长 25.00 秒，超过视频时长 20.00 秒
```

不强制禁止，因为视频可以循环播放。

---

## 14. 动作与视频关系

动作列表不绑定视频。

```text
视频 = 临时预览素材
动作列表 = 机械屏运动编排
```

因此：

- 可以先编辑动作，再加载视频预览。
- 可以换不同视频使用同一套动作。
- 导出的动作 JSON 更干净。
- 后续可以直接给硬件控制系统使用。

---

## 15. 推荐开发优先级

### 第一批

1. 选择 / 全选 / 清除移到编辑器顶部。
2. 增加选择模式。
3. 点击单元选择/取消。
4. 拖动框选单元。
5. 运动类型改为同步伸缩、横向波浪、纵向波浪。
6. 参数改为幅度、单次时间、次数。
7. 去掉速度。
8. 增加动作列表。
9. 增加保存修改。
10. 增加上移/下移。
11. 增加新建/载入/导出动作列表。

### 第二批

1. 视频时间轴。
2. 动作时间块。
3. 拖动时间点同步动作。
4. 播放动作列表。
5. 当前动作高亮。
6. 超出/不足视频时长提示。

### 第三批

1. 删除动作。
2. 复制动作。
3. 未保存修改提示。
4. 动作重命名。
5. 动作列表名称。

---

## 16. 目标体验

最终使用流程应尽量简单：

```text
1. 加载视频
2. 点击全选
3. 选择横向波浪
4. 设置幅度、单次时间、次数
5. 点击预览效果
6. 满意后点击增加动作
7. 继续添加动作
8. 导出动作列表
```

核心目标：

```text
选单元 → 做动作 → 排时间
```
