mcpField
I
illustration-ink-sketch

illustration-ink-sketch

github.com/mengto创意与媒体7.1k291 次安装3 天前更新
代码仓库

关于 illustration-ink-sketch

面向设计与编码任务的插画技能,指导创作手绘墨线风格的卡通生物或物件。角色常以身体形态承载编码隐喻,并配有晃动笔触、松散色彩和夸张眼睛。

主要功能

  1. 01手绘笔刷轮廓
  2. 02松散的标记色块
  3. 03大眼睛与表情细节
  4. 04编码主题角色与道具
  5. 05可复现的 SVG 生成工具

适用场景

  1. 01绘制加载状态主题图
  2. 02表现错误或冲突场景
  3. 03制作产品问候插画

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mengto/skills --skill illustration-ink-sketch

安装后在 Claude Code 中输入/illustration-ink-sketch确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

style.json
agents/
openai.yaml
demo/
PROMPT.md
examples/
hello-world.svg
merge-conflict.svg
slow-build.svg
references/
craft.md
scripts/
ink-kit.mjs
lint.mjs
render.mjs

详细介绍

插画:墨线速写

潦草的手绘墨线卡通:一只眼睛圆滚滚的小动物或物件(蜗牛、一对蠕虫、一盆仙人掌),身体承载着编程隐喻;用摇曳的笔刷笔画在随意涂抹的马克笔色块上。适合轻松俏皮的产品场景:加载、错误、问候、冲突。

界限:人物使用干净、均匀的约 2 px 墨线轮廓并填充纯色时,使用 illustration-outlined-cartoon。人物使用黑色笔刷马克笔并搭配一种薄荷色时,使用 illustration-two-colour-brush。动物柔和温馨、不勾勒轮廓且带有颗粒质感时,使用 illustration-grainy-gouache。

本文提取自一组包含 14 种风格的 42 张原创设计与编码卡片;examples/ 中的三张卡片是此风格已发布的卡片。

一句话概括风格

每条边缘都是填充的黑色笔刷多边形,宽度从约 1 px 膨胀到 4.4 px,再逐渐收尖;用几笔彼此分开的笔画绘制在色块上,色块会超出轮廓 2 到 3.6 px;深色区域用排线表现,不直接填满。

配色

根据示例测量得出。每个颜色系列依次为基础色/深色/浅色;深色用于斑驳纹理和马克笔笔迹,浅色用于一道受光笔迹。

角色十六进制值用途
卡片背景#ffffff(不绘制)不要绘制背景矩形。
墨线#1d1a18所有轮廓、排线、头发、斑点、瞳孔、文字。切勿使用纯黑色。
红色#f0563d / #b8311f / #ff8a6a,深色 #9a2414壳、花盆、一只蠕虫
黄色#ffc83d / #ef9a24 / #fff1b0蜗牛身体、爆发状火花、花心;#fff1b0 也用于气泡阴影
绿色#5cb946 / #2f8a38 / #a6dc62草地色块、仙人掌
蓝色#66cdea / #2a8fbf,水滴 #bfe8f7黏液、马克杯、进度条填充、汗滴
青绿色#2fb5a7 / #167a71 / #8fe3d6,深色 #0f5c55红色角色旁边的另一个角色
木色#eaa85c / #b8722f / #f8d6a0,深色 #8a5320书桌、桌子
腮红色#ff7f86(不透明度 0.5 到 0.75),短线 #d9434f 或 #c8303f带有三道短线的脸颊圆斑;舌头
眼部阴影#c9d6ea每只眼睛白色部分内的月牙形阴影
纸张色#fffaf0,折痕 #d9d2c4贴纸、碎纸片、标签
单独使用的颜色嘴巴 #3b1f1a、花瓣 #ff8fa0、土壤 #5b3b2c、咖啡 #6b4330、柔和阴影 #7f97ab(不透明度 0.22)一次性细节
白色#ffffff眼白、光泽笔触、对话气泡、高光
  • 主体使用两个颜色系列,地面另加绿色(红色 + 黄色的蜗牛、红色与青绿色的蠕虫、绿色仙人掌 + 红色花盆 + 木色书桌)。第三个系列只用于小道具。
  • 切勿使用渐变。仅在斑驳纹理、笔迹、光泽和腮红处使用透明度。面积大于瞳孔的纯黑色区域绝不可出现:应改用排线表现。

线条与填充

所有墨线都是笔刷绘制的填充多边形(工具包中的 stroke()),绝不用 SVG 描边:示例中 stroke 属性的数量为零。

标记宽度为 480 时的数值
轮廓OUT(centre):w 4.6、最大 4.4、最小 1.0、压力 0.4(波长 26)、笔尖 0.3,右下方阴影侧更粗(k 0.3 至 0.36)。首尾收尖 t0/t1 为 3 至 30 px。每个形状由 3 至 6 条分离的笔画构成,在左上受光侧留一个缺口,并有一处超出 2 至 14 px
次要线条(边缘、气泡尾巴、嘴部)w 2.4 至 3.2、笔尖 0.45、压力 0.4、pf 8
细节(肋条、皱纹、木纹)w 1.1 至 1.8,墨色不透明度为 0.55 至 0.85
排线w 1.0 至 1.15、间距 2 至 3.2、角度 -48 至 -58 度(右侧受光的形状则镜像为 -130 度),末端在边缘内侧抖动
毛发每条轮廓笔画 2 至 5 根,w 0.9 至 1.5、长度 2.5 至 7,阴影侧朝外
墨点每张卡片 9 至 11 个,大小 0.8 至 1.7,放在空白边缘处
填充基础颜色,偏离轮廓 2 至 3.6 px(fillShape off),控制点抖动 1.2 至 1.6
斑驳在每块填充上应用斑驳滤镜,使用深色,透明度 0.36 至 0.5
马克笔笔痕深色,w 4 至 16、透明度 0.3 至 0.55,沿阴影侧画 1 至 3 道,并裁剪到形状内
高光白色,w 2.4 至 6、透明度 0.85 至 0.95,在圆形物体左上受光处画一到两道笔痕

每张卡片使用两个滤镜,且都带有前缀:rough(分形噪声 0.45、位移 0.7)包裹整张卡片,让每条边缘都颤动;mottle(噪声 0.035 x 0.06、3 个八度、alpha 2.6/-1.25)遮罩水彩色块。svgOut 会写入这两个滤镜。

角色

不画人。主角是小动物或有生命的物体(蜗牛、虫子、仙人掌;也可以是杯子、虫子、扫地机器人),其身体本身就是隐喻:蜗牛壳是加载旋转图标,虫子的细尾巴是带有提交点的 git 分支,花盆上贴着一个 </> 贴纸。

  • 身体: 沿脊柱绘制管状结构并使用宽度函数(tube()),或通过 12 至 24 个控制点绘制闭合的团块。管状身体末端鼓起形成头部(身体 40、头部 49)。主体约占卡片宽度的 60% 至 70%。
  • 眼睛,标志性特征: 巨大的凸眼,半径 19 至 27.5(直径 40 至 55 px,占头部宽度的 1/3 至 1/2),通常是一对大小略有不同、相互接触或重叠的眼睛。白色圆盘,右下方有 #c9d6ea 色阴影弧,眼眶在起笔处鼓起并越过起点;瞳孔半径为眼睛半径的 0.5 倍,朝角色注视方向偏移 4 至 10 px;一个大高光和一个小白色高光。用身体颜色的眼皮(h 0.34 至 0.38,倾斜 17 度)表现不悦。
  • 面部: 腮红椭圆为 8 x 4.6,带三道短红线;微笑由一条弯曲笔画和两端的短小笔触组成,欢呼时用填充的深色嘴巴并加粉色舌头,生气时画白色咬紧牙齿的形状并加两条牙缝线,撅嘴时画向下弯曲的笔画和下唇。
  • 手部,需要时再为角色添加: 使用四肢颜色;手掌和 3 根手指加一根拇指均为胶囊形,指关节处不闭合描边,并添加一道指关节皱纹和阴影侧的深色笔痕(工具包中的 hand())。大小参照仙人掌:在缩放 1.25 时,手指长 12 至 14.5。拇指的位置按 references/craft.md 中的左右手惯用性表格设置。
  • 触角、茎、尾巴: 使用两侧带轮廓的渐细管状结构,或单条螺旋笔刷笔画。若使用细腿,则用单条宽 2.4 至 3 的笔刷笔画,末端画小的填充椭圆。
  • 短腿和爪子(小型哺乳动物): 使用 shadeTube + limbOutline({ under: bodyLoop }) 绘制宽 9 至 14 的短管状结构,末端画一个 5.4 x 3.2 的花瓣粉色椭圆,并在下方加一道短墨线。先画远侧的一对,再画身体,最后画近侧的一对;后腿朝臀部后方倾斜,前腿朝肩部前方倾斜,让角色看起来在奔跑。
  • 用力与情绪标记: 汗滴、由四个弯曲括号组成的愤怒标记、运动弧线(两条同心笔画,宽度分别为 2.4 和 1.8,逐渐收尖)、蒸汽卷曲线。

装饰与道具

  • 地面(任选其一): 一片参差的草地,范围从 x 52 延伸到 428,顶边位于 y 272 到 280,底边向上弯起,两端带有干刷笔触、草叶飞笔和一两簇高高的草丛(grassPatch、tuft);或者一张略微俯视的木桌桌面,带有木纹线条和一条排线桌腿。
  • 接触阴影: 每个着地部位正下方画一个排线椭圆(w 1.0,sp 3 到 3.2,op 0.85 到 0.9),再在身体底部加一道颜色更深的笔触。道具必须有所依托:标牌要插在草地里的木桩上,杯子要放在桌面上。只有气泡、飞散纸屑和标记可以悬浮。
  • 道具,1 到 3 件: 一个 </> 代码贴纸、一个带手写文字的对话气泡、一张带代码尖括号的撕纸、一只冒着蒸汽卷曲线条的杯子、一条进度条(白色轨道、蓝色排线填充、手写百分比)、提交圆点、爆裂星形、一朵花。
  • 文字: 用笔刷笔触手写(w 2.4 到 2.6,字形高 12 到 17 px),绝不使用字体。
  • 切勿使用: 没有笔刷轮廓的规整几何矢量形状、渐变、投影、纯黑填充、背景场景、人物。

构图

  • 不要背景矩形。所有内容都须位于 x 36 到 444、y 40 到 340 之内;只有干刷地面两端可以延伸到 x 36。
  • 主体位于地面中央偏下,宽度约占卡片的 60% 到 70%,高度约占 60%;眼睛是上半部分的视觉焦点。用一个气泡、纸屑或标记填补最空旷的上方角落。圆形或高挑的主体(如轮子、花盆)宽度只占约 50%;在一侧加一个落地道具填满画面宽度。
  • 本技能中的所有数值均以卡片尺寸为准。在缩放组内部,按「数值 / scale」绘制,并先在卡片坐标中确定接触点(如爪子放在边缘上、花盆放在桌面上),再将其映射到组内坐标:const G = w => [B0[0] + (w[0] - B0[0]) / S, B0[1] + (w[1] - B0[1]) / S]。
  • 在设计尺寸下,于地面接触点周围使用 <g transform="translate(cx gy) scale(1.12) translate(-cx -gy)"> 绘制主体,并设置 setWScale(1/1.12),使线条宽度保持不变,之后再设置 setWScale(1)。
  • svgOut(file, {shift: [0, -8]}) 可移动整张卡片,以平衡边距。

技法

scripts/ink-kit.mjs 是生成三个示例所用的带种子的笔刷库:将其放到原文件的位置运行,Merge Conflict 和 Hello World 生成器会精确复现已发布卡片中的每一笔(唯一差异是旧文件写入器在 <defs> 中留下了一个多余的文本节点)。每一笔都使用一个具有独立随机序列的字符串键,因此编辑或添加一笔都不会打乱其余笔画;更改某个键即可重新生成单独的一笔。

// card.mjs, next to a copy of ink-kit.mjs
import * as K from './ink-kit.mjs';
const { PAL, OUT } = K;
K.setPrefix('xx-');                                        // every id: filters and clip paths
K.grassPatch('grass', { x0: 60, x1: 420, top: 276, bot: 320 });
K.hatch('cast', K.arc(240, 286, 70, 6, 0, 360, 10), { ang: -58, sp: 3, w: 1.0, inset: 1.2, over: 0.4, op: 0.9 });
const ctrl = [];                                          // a round body: control points
for (let a = 0; a < 360; a += 30) ctrl.push([240 + 70 * Math.cos(a * K.deg), 220 + 62 * Math.sin(a * K.deg)]);
const loop = K.fillShape('body', ctrl, PAL.red.c, { off: [-3, 2], j: 1.4 });   // slipped fill
K.mottle(loop, PAL.red.d, 0.46);
K.clipOpen(loop);                                         // shading stays inside
K.stroke('streak', K.arc(240, 220, 60, 54, -10, 120, 6), { w: 13, t0: 20, t1: 25, wob: 1.5 }, PAL.red.d, 0.45);
K.stroke('gloss', K.arc(240, 220, 52, 48, 198, 236, 4), { w: 6, t0: 8, t1: 12 }, '#ffffff', 0.95);
K.clipClose();
const dl = K.resample(K.catmull(ctrl, true, 10), 1);      // outline in two strokes: gap top-left, overshoot
const o1 = K.stroke('o1', K.loopSlice(dl, 0.62, 1.18), { ...OUT([240, 220]), dense: true, t0: 12, t1: 10 });
K.stroke('o2', K.ext(K.loopSlice(dl, 0.2, 0.58), 3), { ...OUT([240, 220]), dense: true, t0: 8, t1: 6 });
K.hairs('hairs', o1.C, 4, { c: [240, 220] });
K.eye('eyeL', [216, 172], 21, [223, 176], 10.5);
K.eye('eyeR', [262, 168], 23, [269, 173], 11.5);
K.blush('blL', 206, 222); K.blush('blR', 280, 218);
[[96, 120, 1.5], [400, 96, 1.2], [420, 230, 1.1]].forEach((p, i) => K.fleck('fk' + i, ...p));
K.svgOut(new URL('./card.svg', import.meta.url).pathname, { label: 'Title, Ink sketch style' });   // next to card.mjs

工具包中的组件:stroke(笔刷)、OUT(c)(轮廓预设)、hatch、fillShape、mottle、clipOpen/clipClose、hairs、fleck、dry、eye(带 lid)、tube 以及 across/acrossLine、shadeTube(为肢体或身体添加填充、斑驳、笔触、高光和肋纹)、limbOutline(只为肢体位于身体外的部分上墨)、hand、grassPatch、blade/tuft、blush、sweatDrop、codeSticker、paperScrap(撕纸便笺;返回用于在其上书写的 T(x, y))、fillRing(正面朝向的轮子或甜甜圈表面:使用奇偶填充和斑驳效果)、arc、loopSlice、ext、runsOutside、setWScale、svgOut。

用一笔刷笔触绘制的符号示例,例如无穷符号(26 px 宽的莱姆尼斯卡特曲线):

const inf = []; for (let t = 0; t <= 2 * Math.PI + 0.35; t += 0.07) { const s = Math.sin(t), c = Math.cos(t), d = 1 + s * s; inf.push([x + 13 * c / d, y + 13 * s * c / d]); }
K.stroke('inf', inf, { w: 3, t0: 3, t1: 5, nib: 0.45, press: 0.3, pf: 8 });

node scripts/ink-kit.mjs --demo $W/demo.svg 会写入演示卡片并打印 wrote <path> 203.5KB 316 elements:一个红色、长着凸眼、在草地上挥舞三指之手的 blob,带有排线、代码贴纸、汗滴和飞散笔点。使用 --prefix ikd- 运行 lint 检查可通过。

常见问题

  • 剪贴画式线条。 笔画宽度一致,或使用 SVG stroke 属性,都会显得像矢量图。每条线都应是带有粗细变化和压力感的笔刷多边形。
  • 封闭的轮廓。 用一个闭合环绕住形状会显得像描摹。将每条轮廓拆成 3 到 6 笔,在受光一侧留一道缺口,并让其中一笔稍微越过轮廓。
  • 填色紧贴线条。 看起来会像涂色书里的矢量图。让每块填色错开 2 到 3.6 px,每个形状的错开方向都不同。
  • 平涂色彩。 没有斑驳、条纹或光泽的填色会显得像印刷品。每块填色都要有斑驳,圆形物体上还要至少加一道深色条纹和一道高光笔触。
  • 纯黑阴影。 用排线处理;通过 keep 让排线密度朝光源方向逐渐变淡。
  • 呆滞的凸眼。 瞳孔居中,或缺少高光,都会让目光显得呆滞。将瞳孔朝动作方向偏移 4 到 10 px;始终加两个白点。
  • 到处都是毛发。 每笔画的毛发超过 5 根,线条就会显得毛茸茸。控制在 2 到 5 根,并放在背光侧。
  • 主体悬浮。 没有排线接触椭圆和深色底部条纹,角色看起来就会悬在草地上方。
  • 缩放组中的线宽不一致。 忘记设置 setWScale(1/s) 会让每条线都粗 12%。
  • 一次编辑后所有内容都变了。 复用或重新编号键会重新生成标记;为每个标记指定稳定且唯一的键。
  • 同一页面上的两张卡片共用一个滤镜。 为每张卡片调用 setPrefix 并指定唯一前缀;使用 --prefix 运行 lint。
  • 排版文字。 对话气泡中的字体会破坏手绘感。用笔刷笔画书写;如果画出字形比笑点本身还费时,就用标记来表达(计数线、V 形符号、图标)。
  • 脸紧挨着道具。 测试中,仓鼠的鼻子、嘴巴和爪子会与滚轮边缘融在一起。脸周围留出 25 px 的空隙,肢体末端也不要接到嘴边。
  • 标记超出纸张。 计数点溢出纸片的撕边后,会像多余的墨迹。在纸片边缘内至少留出 4 px。
  • 悬空的标牌。 主体旁边悬在空中的便条看起来像画错了;用带排线的接触阴影将它固定在支杆上。

示例

  • slow-build.svg(缓慢构建):一只满头大汗的蜗牛趴在 27% 进度条上,壳是带排线彗星扫尾的螺旋加载图标;展示眼柄、代码贴纸、草地、手写的 % 和柔和的接触阴影。
  • merge-conflict.svg(合并冲突):一只红色虫子和一只青绿色虫子在分支线交汇处迎头相撞;展示管状身体和分节环、皱眉的眼睑、咬紧的牙齿和撅起的嘴、提交点、爆裂火花、愤怒标记,以及一张被甩出去的 <<<< 纸片。
  • hello-world.svg(Hello World):桌上的盆栽仙人掌挥手说“你好,世界”,旁边放着咖啡杯;展示拇指方向正确的三指挥手、搭在花盆边缘上的手臂、带有刺状短线的棱纹、木纹、弯曲的蒸汽,以及对话气泡中的手写字。

工作流

从此技能文件夹运行。render.mjs 需要在此处、当前文件夹中或全局安装 playwright-core(或 playwright),并且需要 Chromium。

  1. 简述。 写明主题和隐喻:是哪种小动物,身体的哪个部位承载这个想法。记下在 480 px 尺寸下最能传达它的一个表情(眼睛、嘴巴、斑纹)。
  2. 主体与姿势。 在纸上或注释中勾勒轮廓:脊柱、眼睛位置、地面线。每只手都标明左/右和掌心/手背(craft.md)。
  3. 设置: W=/tmp/ink-card; mkdir -p $W; cp scripts/ink-kit.mjs $W/,然后根据 Techniques 骨架编写 $W/card.mjs,并使用唯一前缀。
  4. 打底: 只画地面、身体底色和眼睛。渲染并检查尺寸、位置和 1 倍大小下的辨识度。
  5. 绘制: 添加阴影(斑驳、条纹、排线、高光)、分开绘制的轮廓线、毛发、面部、道具、文字、斑点。
  6. 渲染: node $W/card.mjs && node scripts/render.mjs $W/card.svg $W/card.png(card.mjs 会在同一目录下写入 card.svg)。
  7. 图版: node scripts/render.mjs --sheet $W/sheet.png examples/*.svg $W/card.svg。问问自己:“画风一致、系列感一致吗?”
  8. 放大眼睛、手、接触点和文字,放大 6 到 8 倍:node scripts/render.mjs $W/card.svg $W/eyes.png --zoom x,y,w,h --scale 8。
  9. 根据 references/craft.md 中的五项标准和 Verify 列表进行审阅;通过编辑生成器来修正(绝不修改 SVG);然后重复操作。预计需要三到四轮。
  10. Lint 检查: node scripts/lint.mjs $W/card.svg --prefix xx- --palette style.json。修复每个 ERROR;每种 WARN 颜色都必须是刻意为之的单次使用。

验证

  • 任何地方都没有 stroke= 属性;每条线都是填充为 #1d1a18 的笔刷多边形。
  • 轮廓线有粗细变化且两端渐细(细处约 1 px,粗处约 4.4 px),每个形状的轮廓线都有断口和延伸段。
  • 每块填色都明显越过线条 2 到 3.6 px。
  • 每块填色都有可见的斑驳;圆形部分带有深色条纹和白色高光笔触。
  • 阴影和深色区域采用 -48 到 -58 度的排线,间距为 2 到 3.2;没有纯黑区域。
  • 眼球直径为 40 到 55 px,瞳孔偏向动作方向,每只眼睛有两个高光点,内部带有阴影弧。
  • 每段轮廓线有 2 到 5 根毛发;边缘留白处有 9 到 11 个斑点。
  • 主体置于一片草地或桌面上,并带有排线接触阴影;没有东西意外悬空。
  • 主体使用两组颜色;地面使用绿色或木色;仅使用调色板中的十六进制颜色。
  • 整张卡片都包在带前缀的 rough 滤镜中;所有 id 都带有前缀。
  • 文字由笔刷绘制,而非使用字体。
  • 不看标题,在 1 倍大小下也能看懂隐喻。

评论

支持 Markdown