ZWMAP 标注类型规范
1. 概述
标注协议遵循机制与策略分离原则:13 种节点类型提供底层 UI 容器,统一动作体系(StandardAction)负责交互行为,业务场景由用户自由组合。使用 在线标注编辑工具 可以可视化创建和编辑交互标注数据。
标注数据是一个统一的 nodes 数组(旧版 hotspots + events 双数组格式已废除,加载时自动迁移旧字段)。
2. ZWMAP 头部
{
"zwp_protocol": "ZWMAP/1.0",
"zwp_type": "annotation"
}
zwp_protocol 和 zwp_type 为必填字段。
3. 13 种节点类型
| 分组 | 类型 | 说明 |
|---|---|---|
| 基础元素 (4) | hotspot / text / image / button |
内联渲染在视频画面上,支持 event.actions 交互 |
| 交互收集 (5) | choice / quiz / form / vote / card |
选项分支 / 测验 / 表单 / 投票 / 信息卡片 |
| 高级展示 (2) | webview / map |
网页 iframe 嵌入 / 地图 |
| 系统流程 (2) | countdown / speed_controller |
倒计时(到期触发动作)/ 播放变速控制 |
节点公共字段
| 字段 | 类型 | 说明 |
|---|---|---|
id |
string | 全文档唯一(必填) |
type |
string | 13 种类型之一(必填) |
time_range |
array | [start, end] 秒(必填,start < end) |
position |
object | {x, y, w, h} 画面百分比 0-100;弹窗类节点可省略(居中显示) |
pause_on_show |
bool | 进入区间时暂停播放 |
mandatory |
bool | 强制节点:跳过会被拉回;未显式设置 dismissible 时弹窗不可关闭 |
hidden |
bool | 初始隐藏(可由 CONTROL_NODE 动态显示) |
z_index |
number | 层叠顺序 |
animation |
object | {enter, emphasis, exit, duration} 动画 |
4. 动作类型 (Actions)
所有交互通过 event.actions[] 数组定义,每项为 { "type": ..., "payload": {...} }:
| type | payload 参数 | 说明 |
|---|---|---|
SEEK_TIME |
target, show_back_btn |
时间轴跳转 |
LOAD_ITEM |
target |
切换播放列表项 |
PAUSE_MEDIA / PLAY_MEDIA |
— | 强制暂停 / 恢复播放 |
OPEN_LINK |
url, pause |
打开外部链接(http/https 白名单) |
CONTROL_NODE |
target_id, operation, auto_hide |
控制其他节点显隐(show/hide/toggle/activate) |
EMIT_MESSAGE |
params, target_origin |
向宿主页面 postMessage |
SUBMIT_DATA |
api_url, method, params |
向外部 API 提交数据 |
SET_VARIABLE |
key, value |
设置会话变量 |
5. 完整示例
{
"zwp_protocol": "ZWMAP/1.0",
"zwp_type": "annotation",
"zwp_version": "1.0",
"nodes": [
{
"id": "hs_link_01",
"type": "hotspot",
"time_range": [3.0, 15.0],
"position": { "x": 10, "y": 20, "w": 25, "h": 15 },
"event": {
"trigger": "click",
"actions": [
{ "type": "OPEN_LINK", "payload": { "url": "https://www.example.com", "pause": true } }
]
},
"style": { "border_color": "#FF6B6B", "border_width": 1 },
"animation": { "enter": "fadein", "emphasis": "pulse", "exit": "none", "duration": 500 },
"hint": "点击查看详情"
},
{
"id": "quiz_01",
"type": "quiz",
"time_range": [60.0, 90.0],
"pause_on_show": true,
"mandatory": true,
"content": {
"title": "知识检查",
"prompt": "以下哪个是正确的?",
"options": [
{ "text": "选项 A", "value": "A", "is_correct": false },
{ "text": "选项 B", "value": "B", "is_correct": true }
],
"feedback": { "correct": "回答正确!", "wrong": "请重试" },
"max_attempts": 2,
"fallback_time": 60.0,
"show_toast": true
}
},
{
"id": "cd_01",
"type": "countdown",
"time_range": [55.0, 62.0],
"position": { "x": 40, "y": 35, "w": 20, "h": 30 },
"content": {
"countdown": 5,
"pause_during": true,
"on_expire": { "type": "PLAY_MEDIA", "payload": {} }
}
}
]
}
6. 约束规则
- 每个
id在整个文档范围内必须唯一 position的值为百分比(0-100),非像素值time_range必须是数组且第一个值小于第二个值- 未知 Action / 节点 type 静默忽略,不导致播放器崩溃;单条非法节点只跳过自身
mandatory弹窗类节点默认不可关闭(除非content.dismissible: true显式允许)