graphite石墨
手绘插画:一个人坐在凳子上喝咖啡,看着小机器人举起马克笔准备在白板上画图 同一幅画的夜间版:房间暗下来,白板变成深色
暖纸paper石墨线graphite彩铅pencils动起来motion怎么画出这种画?How is it drawn?一支笔,按讲故事的顺序画one pen, in story order
sky-skills · 第 11 个设计风格sky-skills · design voice no. 11

用铅笔,把一件事讲清楚Explain it in pencil

暖纸、石墨线、几支彩铅。画面像随手画的草图,一笔一笔按讲故事的顺序画出来。拿它做讲解页、短视频、动图、壁纸都行。上面这幅插画是出图模型画的,白板上那张图是代码当场画的,两者叠在一起用。用得越久,它越懂你喜欢什么样的画。Warm paper, a graphite line, a few coloured pencils. It looks like a quick sketch and draws itself stroke by stroke, in the order a story is told. Use it for explainer pages, short videos, animations, wallpapers. The picture above came from an image model; the diagram on the whiteboard is drawn by code, live, on top of it. And the longer you use it, the better it knows the drawings you like.

定死的只有五样Five things are fixed

这五样就是这个画风,别的都随你These five are the look. Everything else is yours.

风格不靠模板,靠材料。换掉其中一样,画面就不是这个画风了;这五样都在,版式、构图、角色、动画怎么做都还是它。The look comes from materials, not a template. Drop one of these and it stops being this style; keep all five and any layout, composition, cast or motion still reads as it.

#f6efe2#131925

1 · 暖纸1 · Warm paper

米色纸底,不用纯白。深色版是藏青墨纸加粉笔线,另画一张,不能把浅色图反相。Cream paper, never pure white. Dark mode is navy paper with chalk lines, drawn again, never an inverted copy.

2 · 石墨线2 · Graphite line

深灰褐,不是纯黑。线会轻微抖,转角处冲出去一点,画的圈首尾对不齐。Warm dark grey, never black. It wobbles, runs a little past corners, and loops do not quite close.

3 · 少量彩铅3 · A few pencils

颜色是来回涂的彩铅线,不是平涂。一张图里一种颜色只干一件事,大片纸面空着。Colour is back-and-forth pencil, not flat fill. Each colour has one job in a figure, and most of the paper stays empty.

手写的字handwritten

4 · 手写批注4 · Hand lettering

图里的说明用手写体(文楷);代码和数字用等宽字。插画本身不写字,字由网页叠上去。Labels in a hand font (WenKai); code and numbers monospaced. Illustrations carry no words; the page lays text on top.

线 → 色ink → colour

5 · 先线后色,一笔一笔5 · Ink, then colour

像一个人在画:按故事顺序,先勾线再上色(时间大约 2:1)。关掉动画时直接显示画好的样子。Like a person drawing: in story order, outline first and colour after (about 2:1). With motion off, the finished drawing shows.

版式构图角色和道具用哪几支彩铅动画怎么动标题字体位图还是代码做成什么:网页 · 视频 · 动图 · 壁纸 layoutcompositioncast and propswhich pencilshow things moveheading typebitmap or codeoutput: page · video · GIF · wallpaper
越用越懂你It learns your taste

用得越久,画得越像你要的样子The longer you use it, the more it draws your way

你挑的每一张、说的每一句「太密了」、留下或删掉的每张图,都记成口味日志里的一行;审查器的意见也记,只是分量轻。AI 画下一张图之前先跑 taste.mjs suggest,拿到按日志算出的参数再动笔。下面三张图是这套算法自己画的:曲线上每个点、每个数,都是 taste.js 在构建时真算出来的。Every drawing you pick, every "too dense" you say, every figure you keep or delete becomes a line in a taste log; reviewers' notes go in too, at a lower weight. Before an AI draws the next figure it runs taste.mjs suggest and draws with the values the log gives. The three figures below are drawn by the learner itself: every point and number is computed by taste.js at build time.

「还是太密了」"still too dense"你you你的反应what you do二选一pick A or B×1说一句say a sentence×1留下 / 删掉keep / delete×0.5审查器的意见a reviewer's note×0.3口味日志taste log只追加,不改写append onlygraphite-taste.jsonl每个旋钮算一个值one value per knobm ← (m·W + x·w) / (W + w)起点算 2 份 · 越旧越轻starts at 2 · older = lighter(半衰期 90 天)(half-life 90 days)审查器reviewers×0.3硬下限(不算口味)hard floor (not taste)手机上字太小 → 字号至少 +2labels too small on phone → +2客观问题objectiveAB下一次:挑一张(只差最没把握的那个旋钮)next: pick one (they differ in the least certain knob)
一圈是怎么转的How the loop turns你的每个反应记一行日志:二选一和说一句各算 1 份,留下或删掉算 0.5 份,审查器的意见算 0.3 份。每个旋钮从日志里算一个加权平均,越旧的记录越轻(半衰期 90 天)。审查器查出的客观问题不算口味,是硬下限,永远不会被淡忘。下一次,它挑自己最没把握的那个旋钮,拿两张只差这一处的图问你。Every reaction is one line in a log: a pick or a sentence weighs 1, keep or delete 0.5, a reviewer's note 0.3. Each knob is a weighted mean over the log, older lines weigh less (half-life 90 days). An objective problem found by a checker is not taste: it is a hard floor and never fades. Next time it asks about the knob it is least sure of, with two drawings that differ only there.
3456100 天没用100 days unused每一格 = 一次反应one step = one reaction密dense疏sparse彩铅间距(hatchGap)pencil spacing (hatchGap)出厂默认 3.7house default 3.7读者心里想要的 5.5(程序看不到)what the reader wants, 5.5 (hidden)给你看的两张the two shown你挑中的your pick学到的值learned说了「还是太密了」said "还是太密了"审查器:「too busy」×0.3reviewer: "too busy" ×0.3旧答案慢慢变轻old answers fade口味变了:想要 4.2taste changed: wants 4.2学到 4.29learned 4.29最后的答案开始一上一下:学到位了answers start to alternate: it has arrived
一个旋钮怎么学到位How one knob learns读者想要疏一点的彩铅(间距 5.5)。出厂是 3.7;答了 10 次之后学到 5.25。100 天没用,旧答案按半衰期变轻,值往出厂回落到 4.92;读者这时改成想要 4.2,又答 7 次,学到 4.29。曲线上每个点都是 taste.js 在那一天真算出来的。The reader wants sparser colouring (spacing 5.5). House value 3.7; after 10 answers it has learned 5.25. 100 days unused: old answers fade and the value drifts back to 4.92. The reader now wants 4.2; 7 more answers and it is at 4.29. Every point is what taste.js computes on that day.
读者甲 · 喜欢干净Reader A · likes it clean「太乱了」 「太密了」"too messy" "too dense"线条抖动wobble0.60彩铅间距spacing5.17彩铅浓淡strength0.39线条粗细line weight1.61出厂默认House default(还没用过)(not used yet)线条抖动wobble1.00彩铅间距spacing3.70彩铅浓淡strength0.52线条粗细line weight2.10读者乙 · 喜欢手感重Reader B · likes it heavy「太死板了,像打印的」 「太淡了」"too stiff, looks printed" "too faint"线条抖动wobble1.41彩铅间距spacing2.86彩铅浓淡strength0.70线条粗细line weight2.70
三个人,三种样子Three readers, three looks中间是出厂样子。左右两位各说了两句话,再各答了 60 个二选一(每次问哪个旋钮,由程序挑它最没把握的那个)。画的内容和随机种子一模一样,不同的只有学到的口味:线条抖动、彩铅疏密、浓淡、线宽。The middle is the house look. The readers on either side each said two things, then answered 60 A-or-B questions (the learner chose which knob to ask each time). Same drawing, same random seed; only the learned taste differs: wobble, pencil spacing, strength, line weight.

自己试一下:挑你喜欢的那一张,它会记住Try it: pick the one you like, it remembers

每一题只改一个参数,左右两张只差这一处。你选一次,参数就往你选的那边挪一点;说一句「颜色太多了」也算。审查器查出的客观问题(比如手机上字太小)会定一条下限,口味再怎么变也不越过去。下面的结果只存在你自己的浏览器里。Each question changes one setting; the two drawings differ only there. Every pick moves that setting a little your way; saying "too many colours" counts too. Objective problems a reviewer finds (labels too small on a phone) set a floor that taste never crosses. What you do here stays in your own browser.

现在的口味Current taste

灰色竖线是默认值,橙色是你的。Grey tick: house default. Orange: yours.

导出的文件交给命令行:node skills/graphite-design/scripts/taste.mjs import 文件,之后 AI 画图前跑 taste.mjs suggest 就按你的口味画。Hand the export to the command line: node skills/graphite-design/scripts/taste.mjs import file; an AI then runs taste.mjs suggest before drawing.

谁来画Who draws it

同一个题目,出图模型和代码各画了一张One brief, drawn twice: by an image model and by code

题目都是「小机器人在白板前准备画图,一个人在旁边看」。左边是本机 Codex 调 gpt-6-astra 出的图,右边是 sketch.js 画的。看完再定谁来画哪种图。Both got the same brief: a small robot about to draw on a whiteboard while someone watches. Left: gpt-6-astra through the local Codex CLI. Right: sketch.js. Decide who draws what after looking.

出图模型画的版本出图模型画的夜间版
出图模型:人、木头、毛衣的质感都到位,深色版要另出一张。画面里的东西不能单独动。Image model: people, wood and wool all read well; the dark version is a second picture. Nothing in it can move on its own.
输入input处理process结果result
代码:简单得多,但每一笔都能动,换主题自动变色,白板上的字和箭头能改。Code: far simpler, but every stroke can move, it recolours with the theme, and the words and arrows on the board can be edited.
画什么What谁画得好Who does it better为什么Why
大场景、电影画面、壁纸Big scenes, film stills, wallpapers出图模型Image model质感和光影代码画不出来;这些画面不需要每一笔都准确Code cannot match the texture and light; these pictures do not need every stroke to be exact
框图、流程图、架构图Block, flow and architecture diagrams代码Code字要对、箭头要连对;出图模型会写错字、连错线Words and arrows must be right; image models misspell and miswire
代码讲解、数学、算法动图Code, maths and algorithm animations代码Code每一步的数是真跑出来的,画面和代码行要同步Each step's numbers come from running it; the picture must keep pace with the code
开场、比喻、片头Openings, metaphors, title shots两个一起Both together位图当舞台,代码在上面画会动的部分(本页首屏就是)The bitmap is the stage, code draws the moving parts on it (as in this page's hero)
图例Figures

37 张图例,32 张会动37 figures, 32 of them animated

每张都由几十行代码画出来,源码、单独的 SVG 文件都能拿走。下面每类挑一张(「越用越懂你」那一类在上面),点进去看全部。Each is a few dozen lines of code; take the source or the standalone SVG. One per kind below ("learns your taste" is further up); click for all of them.

角色与道具 · 3Cast and props · 3

小机器人、人物、常用物件a robot, people, everyday objects

对了!got it!

场景插画 · 2Scenes · 2

一幅画讲一个比喻one picture, one metaphor

那天晚上,雨一直没停。That night the rain never stopped.

电影画风 · 2Cinematic · 2

黑边、单一光源、镜头慢推letterbox, one light, a slow push

界面层Interface网页 · Appweb · app接口层API鉴权 · 限流auth · rate limit业务层Services下单 · 支付 · 通知orders · payments · mail数据层Data数据库 · 缓存database · cache请求request结果answer

框图与架构 · 5Block and architecture · 5

请求沿着层往下走a request walking the layers

收到请求request in缓存里有吗?in the cache?直接读缓存read the cache有yes查数据库query the DB没有no写进缓存save to cache返回给用户reply没命中:约 20 ms(示意)miss: ~20 ms (illustrative)命中:约 1 ms(示意)hit: ~1 ms (illustrative)

流程图 · 2Flowcharts · 2

小圆点走的快慢就是要讲的事the dot's speed is the point

put Aput Bput Cget Aput Dget Bget Cput Emap(哈希表)map (hash table)headtail双向链表doubly linked list← 最近用过← most recent最久没用 →least recent →lru.jsget(k) { const n = map.get(k) if (!n) return MISS list.moveToHead(n) return n.val}put(k, v) { if (map.size === CAP) { const old = list.popTail() map.delete(old.key) } const n = list.addHead(k, v) map.set(k, n)}示意:put 已有的键(改值、挪到最前)这里省略sketch: put on an existing key (update, move to front) left outAA BA B CA CA C DC DC D EABCDEput A:还有空位,A 放到最前面put A: room left, A goes to the front放入input B:还有空位,B 放到最前面put B: room left, B goes to the front放入input C:还有空位,C 放到最前面put C: room left, C goes to the front放入inget A:命中,map 一步找到,挪到最前面get A: hit — found via the map, moved to the front命中hitput D:满了,先淘汰最后面的 B,再把 D 放最前put D: full — drop B at the back, D goes in front淘汰 Bout B没有 B → MISSno B → MISSget B:未命中(B 刚才被淘汰了)get B: miss (B was evicted)未命中missget C:命中,map 一步找到,挪到最前面get C: hit — found via the map, moved to the front命中hitput E:满了,先淘汰最后面的 A,再把 E 放最前put E: full — drop A at the back, E goes in front淘汰 Aout A8 次请求:命中 2 · 未命中 1 · 淘汰 28 requests: 2 hits · 1 miss · 2 evicted两样东西各管一件事:map 管「在不在、在哪」,链表管「谁最久没用」map: is it here, and where · list: who is oldest

代码大白话 · 5Code in plain words · 5

LRU 缓存:哪一行在跑,链表就怎么动an LRU cache: the running line moves the list

t虚线:要拼出的方波dashed: the square wave we wantf(t) = 4/π · ( sin t + sin 3t/3 + sin 5t/5 + sin 7t/7 + … )方波 = 一串正弦波叠起来:频率 1、3、5、7 倍,频率越高越小a square wave = sines stacked up: 1, 3, 5, 7 times the frequency, each smaller1 项:只是一条正弦1 term: just a sine12 项:肩膀开始变平2 terms: the shoulders flatten1/33 项:边更陡了3 terms: steeper edges1/54 项:已经很像方波;边角冲高 18%4 terms: nearly square; 18% overshoot at the corners1/71×2×3×4×5×6×7×8×傅立叶变换算的就是右边这张表:A Fourier transform computes this table:有哪些频率,各占多少(偶数倍是 0)which frequencies, and how much (even ones: 0)红点转一圈 = 方波走完一个周期one turn = one period of the wave

数学与算法 · 9Maths and algorithms · 9

方波是一圈圈正弦叠出来的,每项同色a square wave from circling sines, each term in its colour

分数(越低越好)score (lower is better)第几次实验run #1.0010.9970.994目前最好 0.9939best so far 0.993948 次实验 · 留下 12 次(含第一次基线,示意数据)48 runs · 12 kept incl. the baseline (illustrative)

数据图 · 2Charts · 2

手画坐标,数要对hand-drawn axes, right numbers

这里是重点the key part圈起来ring it这一句要读两遍read this one twice荧光笔划过的字highlighted words对right不对wrong123这一段this part便签:回头再看note: come back to this贴歪一点更像真的a little crooked looks real手画边框的提示框a hand-drawn callout box

标注与叠层 · 4Marks and overlays · 4

圈、箭头、便签、终端卡rings, arrows, notes, terminal

动起来Motion

拖一下进度条:每一秒的画面都是定的Drag the slider: every second is a fixed picture

动画全是 CSS,时间由代码算好写进去。所以能暂停、能逐帧拖,导出视频时第 300 帧永远是第 10 秒那个样子。The motion is plain CSS with times computed by code. So it pauses, scrubs frame by frame, and frame 300 of an exported video is always what second 10 looks like.

count.jslet count = 0for (const box of boxes) { if (box.hasApple) count++}count = 0count = 1count = 2count = 3五个箱子都看过了:3 个苹果。All five boxes checked: 3 apples.机器人和箱子是比喻robot and boxes: a metaphor
0.0 s
  1. 一支笔。One pen. 同一时间只画一样东西,每一笔的时长和它的长度成正比。One thing at a time; each stroke takes time in proportion to its length.
  2. 按故事顺序。Story order. 先场景,再主角,再动作,最后结果。不是从左到右扫。Setting, then the subject, then the action, then the result. Not a left-to-right sweep.
  3. 先线后色。Ink, then colour. 每组里勾线占三分之二的时间,上色占三分之一。In each group, outlines take two thirds of the time and colour one third.
  4. 一个时钟。One clock. 画面、代码高亮、计数都挂在同一条时间线上,所以永远对得上。Picture, code highlight and counter hang on one timeline, so they always agree.
  5. 关掉动画也完整。Complete with motion off. 系统设置了「减少动态效果」,就直接显示画好的结果。With reduced motion set, the finished drawing shows at once.
作品Work

这个画风是从哪来的Where this look comes from

先在 ai-doc 的论文图解里用起来:讲 autoresearch 那一篇,开场是「人睡了,小机器人在电脑前替他做实验」。插画由出图模型画,屏幕上的数据由网页叠上去。画法最早借鉴自开源的 srt-whiteboard-animation(MIT)。It started in ai-doc's paper explainers: the autoresearch one opens with "the person sleeps while a small robot runs experiments". The image model drew the room; the page lays the data on the screen. The drawing technique was first borrowed from the open-source srt-whiteboard-animation (MIT).

ai-doc autoresearch 图解的开场画面:早上 6 点,人醒来,机器人挥手,屏幕上是 83 次实验的分数曲线
ai-doc · autoresearch 图解的开场:插画 + 网页叠加的数据卡。打开图解ai-doc · the autoresearch explainer: illustration plus a data card laid on by the page. Open it
ai-doc 插画:夜里人睡着,窗外是月亮同一幅画的夜间版
ai-doc · 夜里那一张。深色模式用的是另画的夜间版,不是反相。ai-doc · the night shot. Dark mode uses a separately drawn night version, not an inversion.
宽银幕插画:黄昏,人和小机器人坐在屋顶边上看城市
本 skill · 电影画风。同一对角色,换成宽银幕和夕阳。更多素材This skill · cinematic. The same two characters, in widescreen at sunset. More assets
给 AI 的用法For the AI

说「手绘铅笔风」「白板动画」就会用上它Say "pencil sketch" or "whiteboard animation"

# 1 画图:代码在 templates/src/,用 sketch.js + props.js 画1 draw: code in templates/src/, drawn with sketch.js + props.js
node skills/graphite-design/scripts/build.mjs
# 2 出片:任何一张图或页面,逐帧导出 MP4 / GIF / PNG2 export: any figure or page, frame by frame, to MP4 / GIF / PNG
node skills/graphite-design/scripts/export.mjs video reel.html reel.mp4 --size=1280x720
# 3 口味:画之前问一下这个人喜欢什么,画完记下对方选了哪个3 taste: ask what this person likes before drawing; record what they picked after
node skills/graphite-design/scripts/taste.mjs suggest
node skills/graphite-design/scripts/taste.mjs say "颜色太多了"

完整说明在 SKILL.md;出图模型的提示词写法在 references/image-prompts.md。Full guide in SKILL.md; prompts for image models in references/image-prompts.md.