手绘墨水素描 是做什么的?
绘制一幅自包含的动画SVG:带有抖动感的墨水线条、线条边缘略微晕染的马克笔水彩效果,绘制在米色纸张上。纯2D平面,正面或侧面视角。线条会“沸腾”(每2帧重新绘制抖动效果),因此即使是静态主体也显得生动,场景可通过 t 添加小幅运动。如需3D等轴测版本,请改用 handdrawn-3d 技能。标签和标题使用内置手绘笔触字体,支持拉丁文和越南文。
工具包:assets/kit.js · 渲染器:assets/render.mjs · 所有函数:references/kit.md(编写场景前请阅读) · 示例:examples/(杯子、苹果、猫、植物、房屋、餐食)。
初始设置(一次性)
PNG/GIF导出需要 @resvg/resvg-js。如果 render.mjs 提示缺失,请在此技能文件夹中运行 npm install。SVG输出无需额外依赖。
绘制前
- 是否可绘制? 若主题是抽象的(如“希望”、“生产力”、“经济”),不要绘制模糊的内容。应说明情况并建议一两个具体的场景(例如“从路面裂缝中钻出的幼苗”),然后绘制用户选择的场景。
- 图表、UI、按钮、交互式内容: 不适用于此技能。
- 动画: SVG始终循环(线条沸腾)。添加一个属于主体的小幅动作(蒸汽、尾巴摆动、眨眼、树叶摇曳),当适合或用户要求时添加;否则仅线条沸腾即可。只有当用户要求静态图(
--still)时才使用单帧SVG。
工作流程
- 部件与视角。 列出主体的真实部件并选择视角:正面或侧面。例如茶壶:壶身、壶盖、壶钮、壶嘴、壶柄、壶足;侧面视角。根据真实部件绘制(边缘、把手、盖子、茎、板、瓦片),而非带有名称的通用轮廓。
- 布局规划。 在场景顶部注释中编写一个小表格:部件、形状调用、方框参数 (x, y, w, h)、颜色。主体约占纸张的65-80%,居中并留有呼吸空间。地面/桌面线约位于页面下方80-88%处。
- 从后向前绘制 在
scene.js中使用工具包:阴影 → 背景物体 → 主体 → 顶部细节 → 标签。优先使用现成组件(k.cat、k.person、k.tree、k.house、k.window、k.leaf……)并调整其选项,而非重新绘制。对于可在旋轮上旋转的任何圆形物体(杯子、壶、花瓶、瓶子、碗、灯具)使用k.turned。对于手柄、茎、尾巴、手臂和树枝使用k.tube。 - 渲染并查看:
使用Read工具打开node <skill>/assets/render.mjs scene.js -o out/scene.svg --png out/scene.png --thumb --gridout/scene.png并查看它。--grid叠加网格会打印坐标,以便读取实际位置。同时查看out/scene-128.png:它必须在128像素尺寸下仍能被识别为主体。 - 修正并重新渲染。 检查:
- 一眼看去以及128像素尺寸下,是否能识别为主体?首先是轮廓:如果轮廓不像“茶壶”,任何细节都无法补救。
- 比例与重叠:手柄连接主体,物体放在地面上,无漂浮或裁剪。
- 光线始终来自左上角(右下角添加阴影/排线)。
- 标签不覆盖在绘图上方或与其他线条交叉。
重复步骤4-5直至正确(通常2-4轮)。然后渲染最终版本 无需
--grid。
未查看PNG前请不要交付。 交付SVG(动画图片)、PNG路径,并展示PNG。如果场景有运动,还需检查几帧(参见动画)。
风格规则
- 统一外观: 墨水 + 扁平马克笔水彩。无纹理或颗粒感。无渐变、发光、投影、模糊、透明度技巧或SVG
<text>(请使用k.text/k.label/k.title)。不要添加原始SVG。 - 颜色: 调色板名称(
red, coral, orange, ochre, yellow, sage, green, leaf, teal, sky, blue, navy, lilac, plum, pink, wood, brown, chocolate, grey, stone, charcoal, white, cream, sand, skin, tan)。每幅画面3-5种颜色加墨水。任何十六进制颜色会自动柔化,但使用调色板名称效果最佳。 - 阴影: 主要体积上使用
shade: true(或0.15-0.35);最多在一两个大物体上使用hatch: true。光线始终来自左上角。 - 线宽: 轮廓线
'outline'(默认),内部细节'detail',小标记和指引线'fine'。 - 可爱圆润: 动植物应柔软圆润,大头、圆点眼睛和小小的腮红椭圆。避免锐利、写实的解剖结构。
- 构图: 一个清晰主体,居中,占据大部分页面。放在某物上的物体下方需有地面阴影(
k.shadow)。 - 文字: 可选左上角的
k.title(...),以及带有指引线的简短小写边距标签(k.label),放置在空白边距中。不要使用覆盖在绘图上的方框或对话气泡。标签使用用户语言。完全支持越南文。 - 画布: 默认1000×1000。对于宽场景使用
export const sheet = { width: 1200, height: 900 }。--transparent可去除纸张背景。
场景模板
// 茶壶,侧面视角。部件:壶身(turned)、壶盖、壶钮、壶嘴(tube)、壶柄(tube)、阴影
export const sheet = { seed: 1 };
export function draw(k, t = 0) {
k.shadow(500, 820, 300, 34);
k.tube([[690, 540], [810, 520], [810, 650], [700, 710]], 34, { fill: 'teal' }); // 壶柄(末端被壶身遮挡)
k.tube([[330, 640], [250, 560], [200, 470]], [60, 26], { fill: 'teal', shade: 0.3 }); // 壶嘴
const pot = k.turned([[150, 0], [230, 70], [250, 180], [210, 300], [170, 330]],
{ cx: 500, y: 480, fill: 'teal', hatch: true }); // 壶身
k.ellipse(500, 480, 150, 22, { fill: 'teal', weight: 'detail' }); // 壶盖
k.blob(500, 445, 30, { squash: 0.8, fill: 'ochre' }); // 壶钮
k.label('好茶壶', { x: 640, y: 300, to: [560, 440] });
}
动画(始终开启)
out.svg 默认是循环动画SVG:通过CSS切换帧,无需脚本,可在浏览器和 <img> 标签中播放(不支持CSS动画的渲染器显示第0帧)。场景接收 t ∈ [0, 1),一个循环。保持简单:最多一个或两个运动物体(蒸汽、尾巴摆动、眨眼、树叶摇曳、烟雾)叠加在自动的线条沸腾上:抖动每2帧重绘,因此即使是静态主体也显得生动。使用 Math.sin(2 * Math.PI * t) 使运动无缝循环。现成组件接收 t:
k.steam(x, y, { t })、k.cat(..., { animate: true, t })、k.person(..., { wave: true, t })。
node <skill>/assets/render.mjs scene.js -o out/scene.svg --png out/scene.png # 动画SVG + PNG静态帧
node <skill>/assets/render.mjs scene.js -o out/scene.svg --gif out/scene.gif # + GIF,可在任何地方播放
node <skill>/assets/render.mjs scene.js -o out/scene.svg --still # 单帧SVG
--frames 8 --fps 10 --boil 2 --gif-size 560
通过查看几帧来检查GIF:ffmpeg -i out/scene.gif -vf "select='not(mod(n\,3))',scale=300:-1,tile=4x1" -frames:v 1 out/frames.png(或检查PNG静态帧,即第0帧)。GIF为256色:宽度请保持在600像素以内。