编辑器状态、控件与导出
模板状态、图片导入、控件显隐、错误状态、导出条件与输出命名。
页面状态模型
编辑器维护以下主要状态:
- 解析后的模板数组;
- 当前模板索引和是否手动选择过模板;
- 每个模板 ID 对应的一份编辑状态;
- 唯一用户图片与其 object URL;
- 当前模板的素材和蒙版资源表;
- 配置、资源、渲染三类错误;
- 配置加载、资源加载和应用进度状态。
每个模板的编辑状态结构:
{
transform: { x, y, scale, rotation },
layers: {
[layerId]: {
opacity,
blur,
backdropBlur,
blendMode,
amount,
color,
recolor,
text?: {
content, x, y, width, height,
font, fontSize, fontWeight, color,
letterSpacing, lineHeight, align, verticalAlign,
fontVariations
},
glass?: {
visible,
transform: { x, y, scaleX, scaleY, rotation },
geometry,
material
}
}
}
}text.fontVariations 保存除 wght 外所有可变字体轴的当前值;glass 状态整体保存几何与材质,编辑器直接修改其子字段。
初始值
初次加载模板时:
- 共享变换使用模板的 scale/rotation 默认值,位置为 0;
- 有用户图片时立即执行动态 cover 和边界约束;
- 每个图层属性使用解析后的默认值;
- 换色组使用各自
default; - text 图层使用默认内容(按
maxLength截断)、默认字号/字重/字距/行高/对齐,fontVariations使用选中字体各轴默认值(不含wght); - glass 图层使用解析后的几何与材质默认值。
配置重新加载与状态合并
配置重新加载后,以新的模板声明为权威,同时尽量保留同模板 ID 的用户状态:
- 数值重新限制到新的控制范围;
- transform 按新模板和当前图片重新约束;
- 已删除图层不再保留;
- 新图层使用新默认值;
- 不再允许的混合模式回退到新默认值;
- 不再允许的整体颜色和换色值回退到新默认值;
- text 内容重新按新
maxLength截断,字号/字重/字距/行高/对齐/文本框重新限制到新范围,字体选项被删除时回退到新默认字体,可变轴值按新字体的 min/max 重设; - 新出现或已删除的可变字体轴会同步到新字体的轴集合。
因此模板和图层 ID 应保持稳定,配置作者不应在无迁移需要时随意改变 ID。
图片导入与替换
- 文件输入接受
image/*。 - 每次只读取一个文件。
- 文件通过 object URL 加载成图片对象。
- 成功替换后,所有模板的 transform 重置为基于新图片的初始变换。
- 每层效果通过状态合并保留。
- 旧 object URL 在不再使用时释放。
- 文件输入值每次处理后清空,允许再次选择同一个文件。
如果当前模板没有 wallpaper 图层,界面不显示选择图片按钮,也不要求输入图片。
模板选择
下拉项显示:
deviceKey · watchface.name当前设备先通过 AstroBox 官方资源设备表解析成资源设备 ID;断连时如果只剩已知的云端 IoT 型号,会通过兼容表转换为同一 ID。模板中的已知旧代号也会在匹配前转换。精确匹配成功时自动选择匹配项。用户手动选择任一模板后,本次页面状态不再因设备信息的后续更新自动切走。
识别过程中显示“正在识别当前设备”。资源设备表无法识别时和配置中没有对应模板时,会分别显示对应原因,两种情况都只支持导出。
连接状态优先来自全局当前设备。如果路由指向另一台设备,则以后端的已连接设备列表为准。设备地址比较忽略大小写和首尾空白,不会因列表项缺少重复的 connected 字段把真实已连接设备误判为断连。
共享取景控件
只有同时满足以下条件时显示“壁纸取景”:
- 已导入图片;
- 当前模板至少有一个
wallpaper图层; - 当前模板状态可用。
提供:
- 缩放滑块、数值输入、重置;
- 旋转滑块、数值输入、重置;
- 居中;
- 适配;
- 全部重置。
缩放数值以百分比显示,旋转以度显示。缩放控件的最小值和最大值会按当前角度动态更新。
舞台同时支持鼠标/单指拖动和双指缩放,详见取景变换、手势与边界算法。
图层控件显隐
只有图层至少存在一个可调属性时,才显示该图层控制区。可调属性包括:
opacity;blur;backdropBlur;amount;blendMode;- asset 整体
color; - 任一可调
recolor组; - text 层的
content、font、fontSize、fontWeight、color、letterSpacing、lineHeight、align、verticalAlign或任一textBox维度的可调属性; glass层始终显示控制区。
固定值不显示控件,但始终参与渲染。
数值控件
每个可调数值同时提供:
- range 滑块;
- number 输入框;
- 单项重置按钮。
显示单位:
| 属性 | 显示 |
|---|---|
opacity | 百分比 |
blur | px |
backdropBlur | px |
amount | 百分比,负值代表暗色覆盖 |
scale | 百分比 |
rotation | 度 |
fontSize | px |
letterSpacing | px |
输入的非有限数值被忽略,合法数值会限制到控制范围。
离散控件
- 混合模式下拉框只列出配置的
options,使用中文标签显示已知模式。 - 整体素材颜色显示配置 options 的色块。
- 每个可调换色组显示自己 options 的色块,标题使用组
name,缺失时使用组id。 - text 层的字体下拉框列出
font.options的name。 - text 层的文字颜色使用
text.color的色块。 - glass 层提供几何形状切换、各材质参数滑块、着色取色器,以及高光/阴影混合模式下拉框。
不提供的图层操作
编辑器没有图层新增、删除、复制、排序、素材替换或蒙版编辑。图层结构始终来自 JSON。
错误分层
配置错误
包括配置请求失败、JSON 语法错误、字段校验错误和缺少安装关联。配置错误会替代整个编辑器内容显示。
资源错误
当前模板任一 asset 或 mask 加载失败时显示资源错误,并阻止导出和应用。
渲染错误
实时舞台捕获统一渲染器异常并显示错误。渲染错误存在时阻止导出和应用;下次成功渲染会清除旧错误。
导出就绪条件
必须满足:
- 当前模板存在;
- 当前模板编辑状态存在;
- 当前没有资源加载;
- 没有资源错误;
- 没有渲染错误;
- 如果模板有
wallpaper图层,已经导入用户图片。
配置加载过程或配置错误本身不会进入具有模板的可导出页面状态。
PNG 导出
导出调用统一渲染器创建与模板 Canvas 等尺寸的 Canvas,并通过 toBlob("image/png") 生成 PNG。
文件名:
{watchface.name 或 template.id}-wallpaper.png浏览器下载链接点击后立即移除,对应 object URL 在 1 秒后释放。
预览、导出和应用一致性
舞台、导出和应用都传入相同的模板、编辑状态、用户图片和已加载资源,并调用同一个 drawWallpaper。预览中的任何差异都应作为渲染问题处理,而不是分别调整导出或应用代码。