关于 illustration-one-line
面向设计与编码任务的插画技能,指导制作动感人物插画。它以单条连续黑线勾勒人物,并用错位的色块呈现轻快场景。
主要功能
- 01单条连续线绘制人物
- 02错位平涂色块
- 03动作姿势与运动线
- 04SVG 卡片生成工具包
适用场景
- 01制作产品发布主题插画
- 02表现冲刺或工作流场景
- 03绘制庆祝时刻的动作人物
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mengto/ skills --skill illustration-one-line安装后在 Claude Code 中输入/illustration-one-line确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
style.jsonagents/openai.yamldemo/index.htmlPROMPT.mdexamples/flow-state.svghackathon-sprint.svgjuggling-tasks.svgreferences/craft.mdscripts/lint.mjsoneline.mjsrender.mjs详细介绍
插画:一笔成画
一种松弛、有活力的风格:以一条漫游的长黑线绘出正在行动的人物,底下铺上错位的色块,仿佛第二种印刷色发生了套印偏移。适合轻快的产品场景(发布、冲刺、流动、庆祝),而室内场景会显得过于厚重。
黑色开放线条搭配网点色调且不使用颜色时,请使用 illustration-halftone-line。用摇曳的笔刷轮廓勾勒可爱小动物时,请使用 illustration-ink-sketch。粗笔刷轮廓搭配实心黑色形状和一种薄荷色墨水时,请使用 illustration-two-colour-brush。
摘自一组包含 14 种风格、共 42 张原创设计与编码卡片的集合;examples/ 中的三张卡片是此风格已发布的卡片。
一句话描述风格
一条连续的黑线绘出整个人物,珊瑚色、长春花蓝和白色的平涂色块置于其后,并刻意错位 2–6 px。
调色板
从三个示例(1x 渲染)中测得:纸色占像素的 87–89%,墨色约占 2%,白色色块约占 3%,长春花蓝占 2.3–3.7%,珊瑚色占 0.8–2.8%。
| 角色 | Hex | 用途 |
|---|---|---|
| 纸色 | #ece7da | 满版背景矩形,方形,不带 rx |
| 墨色 | #1d1b1a | 单条线、每个道具线条、代码字形、速度线、眼睛、实心圆点 |
| 珊瑚色 | #f2846e | 脸部和手部色块、上衣条纹、太阳、每个道具的一块点缀色块、代码短划线 |
| 长春花蓝 | #8790f4 | 裤子、头发、屏幕和道具、地面色块、代码短划线 |
| 白色 | #ffffff | 上衣和袖子、鞋子、杯子、云朵、地面色块 |
- 遮罩中仅在
<mask>内使用#fff和#000;它们不会显示出来。 - 禁用:其他颜色、渐变、不透明度、色块描边、灰色、第二种墨色、面积大于 1.9 px 圆点的黑色填充。
- 珊瑚色用于肤色和小面积点缀;不得用于填充裤子或整件上衣。长春花蓝不得用于填充肤色。
线条与填充
- 单一墨色组:
<g id="xx-ink" fill="none" stroke="#1d1b1a" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round">。每条墨色路径均继承该组样式。 - 画布宽度为 480 时的线宽:人物线条和道具为 2.3;长运动路径或时钟指针为 2.0–2.1;代码字形(
</>)为 1.8;珊瑚色条纹为 1.9;编码色彩短划线为 2.3。 - 人物必须由一条路径(
id="xx-figure")绘成,使用平滑三次曲线段,坐标保留 1 位小数。仅眼睛、下摆或袖口、道具可使用单独的短线条。每个道具也必须各自用一条漫游线绘制。 - 平滑感来自样条曲线:每个路径点为
[x, y]或[x, y, k],其中 k 为张力值(1 表示平滑;0.4–0.6 表示肘部、膝盖和衣领处的柔和转角;0 表示字形的锐利拐角)。 - 线条不得构成色块边界。色块为单独的闭合形状,先绘制在
<g id="xx-patches">中,再在<g id="xx-accents">中绘制条纹和短划线,最后绘制墨色线条。 - 错位效果:每块色块都相对其着色形状偏移 2–6 px(
T(pts, dx, dy)),并让边缘呈波浪状(wobble;手部和脸部的振幅为 0.8–1.5,四肢为 1.4–2.4,大面积色块为 2.2–3)。每块色块使用不同的整数种子。让色块在一侧留出空隙,在另一侧溢出。 - 条纹:上衣上画 3–5 条珊瑚色线条,沿身体曲线走向,在线条轮廓前 2–4 px 处停止,线宽为 1.9。袖子上画 1–2 条短条纹。
- 遮罩:当线条经过某物后方时(例如手臂在笔记本电脑后方、拳头握住警棍,或运动路径经过抛接的物体后方),使用
<mask>,以黑色绘制前景形状的轮廓,将其遮去。添加 2–10 px 的黑色描边,以留出间隙。使用C.mask()生成遮罩。
角色
- 比例:动态姿势中的人物高 190–240 px(占卡片高度的 53–67%)。头部高 41–48 px,约为 1:5。四肢呈管状:手臂在肩部宽 18–21 px,向手腕渐窄至 8.6–9.5 px;腿部从髋部的 27–28 px 渐窄至脚踝的 12–13.5 px。
- 头部:侧脸朝向前进方向,高 41–48 px。轮廓可以朝任意方向绘制。从喉部向上接入
FACE_R(下巴、嘴唇、鼻子和眉毛以柔和拐角绘制),越过头顶和头发,再沿着圆润的后脑勺向下至颈背。也可以反向绘制,即rev(FACE_R)。EAR_RC 形回环可有可无。如果在 8x 下看不清,就去掉:测试中,耳朵加上平直的发际线会让头部看起来像头盔。眼睛是单独绘制的短闭眼弧线(EYE_R),不画嘴部线条(侧脸轮廓已呈现笑容)。珊瑚色面部色块覆盖脸部前半部分,向侧脸方向偏移 1–2 px,后脑勺则保留纸张本色。 - 头发:在头发轮廓后绘制一块长春花蓝色块(马尾、发髻环或短发),或者用圆旋轮线环绘制卷发(
curls(),r 3–3.5,4–5 个环),不加色块。 - 躯干:不单独绘制躯干轮廓。背部轮廓、手臂两侧和腹部都是路线的一部分。用白色上衣色块覆盖胸部,偏移 −4、−3;再以手臂中心线为基础用
blob()绘制白色袖子色块。 - 四肢:分别用
tube(centreline, widths)绘制,并沿一侧向下绘制,绕过手或鞋,再沿另一侧向上返回。在肘部或膝部的点设置 0.4–0.6 的张力,使弯曲清晰。握持物体的手腕与肩部保持 45–60 px 的距离:手柄距肩部 48 px 时,测试手臂会折成鸡翅状(前臂 15 px,上臂 33 px)。 - 手与鞋的连接处:在 8x 下检查四肢边缘与放置的形状相接的位置。如果形状的第一个点落在四肢边缘后方,线条会向回钩。删除该点(
shape.slice(1))或将形状移动 3–4 px。 - 跨坐或坐在道具上(火箭、凳子、椅子):只画靠近观者的一条腿,并置于道具前方;用人物自身的路线作为剪影遮住道具的线条(
C.mask('m-rider', [[route, 5]]))。此时,让路线从同一点开始和结束,例如脚跟处。 - 手部绘制为小型松散环形,长 19–27 px(局部形状 × 1.1–1.3),后方加上偏移 2–3 px 的珊瑚色色块。工具包中的形状:
HAND.mitten(摆动姿势,带拇指凹口)、HAND.fist(环握手柄,带指节凸起)、HAND.tray(托物品的张开手掌)、HAND.open(接东西,拇指向外弯曲)、spreadHand()(挥手,四个独立手指环和一个拇指)、CLAMP(从侧面握住边缘的拳头)。不要画普通椭圆。 - 左右手:根据
references/craft.md中的表格,确定 LEFT 或 RIGHT、PALM 或 BACK,以及手指方向;然后翻转形状(place(..., flip)),让拇指凸起位于对应一侧。scripts/oneline.mjs中每个形状上方的注释都会说明拇指位于哪一侧。 - 脚部:使用
SHOE环形,长 30–35 px(× 1.25–1.3),并加上偏移 3–4 px 的白色色块。允许在一只鞋上添加小型后跟环。 - 环形:每个人物绘制 2–4 个草写环,半径 3–5,位于腰带、脚跟、膝盖、发髻或马尾末端(
loopAt()、cornerLoop())。环过多看起来会像乱涂。在腿部中间绘制环会显得像错误。 - 姿势:幅度大且呈斜向,绝不静止站立。可在两个物体之间跳跃、身体前倾 11° 冲刺,或单腿平衡并抛接物品。绘制路线前,先围绕髋部旋转上半身的点(
rot()),让上半身倾斜。
装饰和道具
- 1–3 个情境道具,每个由一条蜿蜒线条和一块偏移的色块组成:花括号
{ }、带有</>的笔记本电脑、秒表、咖啡杯、虫子、画成加载圆环的太阳。道具融入动作:一条曲线延伸至秒表,一条循环路径穿梭于抛接的物体之间。 - 动态效果:人物身后画 3 条平行速度线(长 26–52 px,间距 13–16 px),或画一条带一个环的曲线轨迹。
- 地面:不要画地平面。在支撑脚下画一条带环的短曲线(宽 90–110 px,脚底下方 1 px),并加一块白色或长春花色块;人物腾空时则不画。
- 代码:在屏幕或指挥棒上用 1.8 px 的线条绘制
</>字符;用珊瑚色和长春花色的曲线短划线表示“代码”(squig(),2.3 px)。 - 禁止:文字、UI 面板、闪光、彩纸、描边方框、地平线、阴影。
构图
- 卡片:首先绘制
<rect id="xx-paper" x="0" y="0" width="480" height="360" fill="#ece7da"/>。然后依次绘制<defs>(遮罩)、色块、点缀、线条。 - 整幅画面宽约 245–377 px、高约 240–284 px,居中。四周各留出 30–40 px 空白(顶部至少 36 px)。
- 人物是卡片的主体:高 190–240 px,摆放时应确保其前进方向前方的空间多于后方。道具放在人物移动方向上或经过的空白处。
- 密度:保持疏朗。纸面占像素的 86–89%;色块约 12–17 个,线条总计 15–40 条。
- 大型道具(火箭、滑板)用一块覆盖其 60–75% 的色块,并偏移 4–6 px。覆盖整个道具的色块会让它看起来像纯白形状,喧宾夺主。大型道具旁的人物应至少高 190 px:如果上半身显得太小,就围绕臀部将其放大。
- 在局部坐标系中绘制,并用一个函数映射到卡片上:
makeCard('sd-', { map: pts => … })会将该变换应用于每条线、每块色块、每个点缀、遮罩和圆点(以中心为基准缩放 1.05–1.1 倍,再平移)。若要让人物朝向另一边,在映射中镜像 x(map: pts => mirrorX(pts, 240));绘制</>字符及任何文字时使用C.raw.line(...),它会跳过映射,因此不会镜像。
技巧
1. 工具包。 scripts/oneline.mjs(无依赖、带种子)包含曲线数学和卡片组装:smooth、tube、blob、wobble、place、T、rev、rot、lowest、curls、squig、loopAt、cornerLoop、arc、局部形状(HAND.*、spreadHand()、CLAMP、SHOE、FACE_R、EYE_R、EAR_R),以及 makeCard(prefix, { map }),其中包含 line、accent、patch、mask、dot(均经过映射)、raw.*(相同功能,但不经过映射)、dots(调试用)和 svg(debug, ariaLabel)。色块和线条共用一个 ID 命名空间,因此色块应以颜色命名(porthole-peri、shoe-white):一张测试卡因两个 porthole ID 未通过 lint。进入技能文件夹运行 node scripts/oneline.mjs --demo /abs/work/demo.svg(将文件写入你的工作文件夹,而不是技能文件夹),然后渲染该文件:一条带连指手套的手臂、一条穿鞋并踩在地面波浪线上的腿、一个侧面头像、色块、条纹和代码短划线。
2. 肢体路径。 沿右侧向下,绕过手,再沿左侧向上:
import { makeCard, tube, blob, place, rev, T, ang, HAND, PERI, WHITE, CORAL } from '/abs/path/to/illustration-one-line/scripts/oneline.mjs';
const C = makeCard('sd-');
const arm = [[150, 120], [170, 132], [190, 146, 0.5], [212, 136], [232, 124]]; // shoulder, elbow (k 0.5), wrist
const W = [18, 16, 13.5, 11, 9], a = tube(arm, W);
const hand = place(HAND.mitten, arm[4], ang(arm[3], arm[4]), 1.2); // +y wrist corner first
C.line('arm', [...a.R, ...hand, ...rev(a.L)]); // in a figure, splice this into the one route
C.patch('sleeve', T(blob(arm.slice(0, 3), W.slice(0, 3), 1.05), 3, -3), WHITE, 1.4, 4);
C.patch('hand', T(place([[0, -5], [12, -5], [17, 0], [12, 7], [2, 6]], arm[4], ang(arm[3], arm[4]), 1.2), 2, -3), CORAL, 0.8, 5);
局部形状从 +y 方向的手腕拐角开始,绕过末端,再到 −y 方向的拐角。若要改为沿肢体左侧向下,请使用 rev(shape) 或 flip = true。
3. 挖空遮罩。 const m = C.mask('m-arm', [[armSilhouettePts, 2]]); C.line('laptop', lapPts, m); 会隐藏手臂下方的笔记本电脑线条。对于穿过多个物体的路径,将每个物体的轮廓与描边宽度 9–10 一起传入,这样路径就会在物体前留出间隙。
4. 让落地的脚踩实地面。 const sole = lowest(route); 然后在 sole[1] + 1.1 处绘制波浪线,使用 T(pts, sole[0], sole[1] + 1.1)。应该站在地面上的脚必须踩在波浪线上,不能悬空。
5. 整个人物的路径顺序(examples/hackathon-sprint.svg 中朝右创作的短跑者)。每条轮廓只经过一次:
后方的地面波浪线 → 落地鞋面 → 后腿前侧向上 → 腹股沟 → 前腿底侧 → 前鞋 → 胫骨前侧 → 膝盖 → 大腿上侧连至腹部 → 远侧手臂底侧 → 拳头 → 远侧手臂上侧 → 肩部 → 短颈 → FACE_R → 头顶 → 马尾 → 后脑勺 → 耳朵 → 后颈 → 近侧手臂上侧 → 连指手套 → 近侧手臂底侧 → 腋下 → 背部 → 腰带环 → 臀部 → 后腿后侧 → 脚跟环 → 鞋底 → 鞋尖 → 前方地面波浪线。
坐姿骑手的路径顺序为:脚跟 → 小腿 → 大腿底侧 → 臀部 → 背部 → 抬起的手臂 → 手 → 后颈 → 头骨 → 发髻环 → rev(FACE_R) → 喉部 → 近侧手臂 → 拳头 → 腹部 → 大腿上侧 → 胫骨 → 鞋子 → 返回脚跟。
6. 色块配方(偏移量 T(dx, dy)、波动幅度,取自示例生成器)。上衣:胸部轮廓,(−4,−3),幅度 2.4–2.6。袖子:blob(arm.slice(0, 3), W, 0.95–1.05),(±2–3,−3),幅度 1.4–1.6。裤子:blob(leg, W, 1.0),(5,3),幅度 2.2–2.4。脸部:头部局部 [[6,-12],[16,-8],[22,2],[19,13],[9,15],[5,2]],(2,−1),幅度 1.1–1.5。头发:(−3,−2),幅度 1.2–1.6。手部:手部的 5–6 点色块,(2–3,±2–3),幅度 0.8–1.2。鞋子:通过鞋子自身的 place() 使用 [[-6,-2],[10,-3],[22,3],[22,10],[4,11],[-7,8]],(3–4,2–3),幅度 1.2。道具:(3–5,±3),幅度 1–1.8。每个种子都要不同。
失败模式
- Hackathon Sprint 在 6.5 分交付。 评委指出头部形状、支撑脚以及较弱的 hackathon 特征。在卡片上,头颅相对马尾显得很小,支撑脚上的环状鞋子看起来像一团,而
</>接力棒加秒表并不能表达“hackathon”。不要照搬那张卡片的头部或后脚,并给人物一个能点明主题的道具。 - 手像连指手套一样一团。 最初的 Flow State 手部是椭圆形。使用带拇指凸起或分开手指的形状,并在后面加一块珊瑚色补丁。
- 膝盖上的环看起来像画错了。 最初的 Flow State 腿部在腿中间画了环,还出现了交叉线。把环放在末端(脚跟、腰带、头发),并让腿从髋部到脚踝逐渐收窄,膝盖弯曲处保持干净利落。
- 颜色恰好与线条完全重合。 这样就成了普通的平涂,失去了印刷错位的效果。让每块补丁偏移 2–6 px,一侧溢出,另一侧则短一些。
- 补丁看起来像污渍。 摆幅超过 3,或斑块与身体部位毫无关联时都会如此。将摆幅保持在 0.8–3,每个部位只用一块补丁。
- 它变成了普通的线稿。 独立笔画太多(躯干轮廓、每根手指、单独的脸)。让人物保持为一条路径;只有眼睛、衣摆和道具单独绘制。
- 物体后方的线条交叉。 路径从手臂或手持物下方穿过,导致两条线都显示出来。遮住被挡住的部分。
- 线宽漂移。 任何地方出现 1.4 px 或 3 px 的描边都会破坏整组图的一致性。墨线使用 2.3,字形使用 1.8,条纹使用 1.9。
- 脚悬空。 支撑脚没有贴在波浪线上。用
lowest()测量鞋底,并将波浪线放在鞋底下方 1.1 px 处。 - id 重复。 补丁和线条使用了相同的名称。给每块补丁的名称都加上颜色后缀。
- 关节处出现钩状线条,手臂像鸡翅。 参见 Characters。这两种问题都出现在自测卡片上,而且只有在 8 倍缩放时才看得出来。
示例
examples/flow-state.svg:“Flow State”。人物跃起,一只手臂向后甩开(采用spreadHand风格的张开手势),靠近的一侧手臂夹住笔记本电脑(CLAMP,需遮罩)。用curls()绘制卷发,搭配耳机、两条用单笔画绘制并带白色补丁的代码大括号、代码短线、作为加载环的太阳、速度线和拖尾波浪线。examples/hackathon-sprint.svg:“Hackathon Sprint”。人物面朝左冲刺:先绘制面朝右的人物,再在G中镜像,</>则绘制在卡片坐标空间中。拳头fist握住接力棒(需遮罩),另一只手挥动mitten,搭配马尾、腰带环、连入波浪线的秒表和速度线。最弱的一张卡片:参见“失败模式”。examples/juggling-tasks.svg:“Juggling Tasks”。人物单腿站立平衡,一只tray手托着笔记本电脑,另一只open手刚放开物品。一条环绕的运动路径穿过杯子和 bug(用描边宽度 9–10 遮罩),地面上有一条带长春花色补丁的短波浪线,头发扎成发髻环。
工作流程
从此技能的文件夹运行每条命令。卡片路径可以是绝对路径。
- 简述。 说出主题和一个能体现主题的动作。选择 1–3 个无需文字就能说明主题的道具。
- 姿势。 用数字勾勒骨架:髋部、肩部、头部中心,以及每条肢体的中心线(各 4–5 个点),并标出宽度。选择朝向和倾斜角度。选择一个 id 前缀(
sd-)。 - 编写生成器(
card.mjs),通过绝对路径导入scripts/oneline.mjs。构建管状肢体,放置手和鞋,并为人物绘制一条路径:从一个自由端(手、脚或地面曲线)开始,绕过每条肢体,最后到达另一个自由端。工作时使用C.svg(true)查看带编号的路径点。 - 手上功夫。 为每只手写明 LEFT 或 RIGHT、PALM 或 BACK,以及手指方向,然后标出拇指一侧(
references/craft.md)。选择形状和翻转方式。 - 上色。 添加色块(偏移、波动、不同的种子)、条纹和遮罩。
- 渲染:
node scripts/render.mjs card.svg card.png。 - 对照图表:
node scripts/render.mjs --sheet sheet.png examples/flow-state.svg examples/hackathon-sprint.svg examples/juggling-tasks.svg card.svg。询问“同一只手,同一套风格吗?”:线条粗细、松弛程度、色块偏移、密度、纸张占比。 - 放大手、头、脚、每个肢体与手或鞋相接的关节,以及每处交叉:
node scripts/render.mjs card.svg z.png --zoom x,y,w,h --scale 8。按照references/craft.md验证拇指。手位于单一路径内,因此无法单独为其重新着色。请改在临时副本中,将红色圆圈(r 2.2)标在拇指尖,蓝色圆圈标在食指尖,两者都通过同一个place()调用映射,然后删除该副本。 - 评审
references/craft.md中的五项标准和 Verify 清单。修正后重新渲染并重新制作对照图表。通常需要四轮或更多。 - Lint:
node scripts/lint.mjs card.svg --prefix sd- --palette style.json。
Verify
- 纸张矩形为
#ece7da,铺满画布,不带rx;只使用纸张、墨色、珊瑚色、长春花色和白色。 - 人物为一个
<path>;除此之外,只能有眼睛、衣摆、道具、速度线和曲线。 - 每条墨色描边宽度为 2.3(字形为 1.8,较长的运动路径为 2.0–2.1);条纹为 1.9 的珊瑚色;端点和连接处均为圆角。
- 没有色块与其轮廓重合:每个色块偏移 2–6 px 且有波动,任意两个色块的种子都不相同。
- 面部色块为珊瑚色,只覆盖脸部正面;眼睛为闭眼弧线。
- 手部有拇指凸起或分开的手指,有珊瑚色块,且拇指位于正确一侧(已完成拇指验证)。
- 末端有 2–4 个环(头发、脚跟、腰带,膝盖最多一次);肢体中段没有环。
- 从手臂或物体后方经过的线条均已遮罩;在 8x 放大时没有意外交叉。
- 姿势呈对角线动态;支撑脚与地面曲线相接,重叠 1 px,或者人物明显处于腾空状态。
- 每条边缘都留有 30–40 px 空白;纸张占比与示例相当(示例为 87–89%);有 12–17 个色块;大型道具的色块只覆盖其 60–75%。
- 在 1x 尺寸下,无需文字,仅凭动作和道具就能看出主题。
- 色块 id 带有颜色后缀,且
lint.mjs --palette style.json通过,没有 ERROR 或 WARN。