illustration-line-interior
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseIllustration: Line interior
插图:Line interior
A calm, editorial line style: a whole room at small scale, people at about one seventh head-to-height, every shape outlined once in thin indigo and filled white, with a few flat accents. It suits product marketing that wants "people at work" without loud colour.
Use for big-headed characters with a near-black ~2.4 px ink line and bold fills. Use when the scene should sit inside a coloured panel on a pastel card. Use when there should be no outlines at all.
illustration-outlined-cartoonillustration-framed-panelillustration-flatExtracted from a set of 42 original design-and-coding cards in 14 styles; the three cards in examples/ are this style's shipped cards.
一种平静的编辑式线稿风格:以小尺度呈现整个房间,人物身高约为头部长度的七倍;每个形状仅以一条纤细的靛蓝线勾勒,并采用白色填充,再加入少量平涂强调色。它适合希望在不使用浓烈色彩的情况下呈现“工作中的人们”的产品营销场景。
对于采用近黑色 ~2.4 px 墨线和大胆填充的大头角色,使用 。若场景应位于粉彩卡片的彩色面板内,使用 。若完全不应出现轮廓线,则使用 。
illustration-outlined-cartoonillustration-framed-panelillustration-flat内容提取自一套包含 14 种风格、共 42 张原创设计与编码主题卡片; 中的三张卡片是此风格已发布的成品。
examples/The look in one sentence
风格一句话概述
One thin, uniform indigo outline (1.4 px) around white-filled shapes in a wide, airy room, with flat colour on under 7% of the card.
在宽敞通透的房间中,所有白色填充的形状外围都采用统一、纤细的靛蓝色描边(1.4 px),并以平涂色彩进行点缀,强调色占卡片面积不超过 7%。
Palette
调色板
Measured from the three examples (fills and strokes, 1x renders). White and the card make up about 85% of the pixels, indigo line about 2%, accents 4–7%.
| Role | Hex | Where it goes |
|---|---|---|
| Indigo ink | | every outline, the floor line, eye dots, indigo hair (hair is a filled ink shape) |
| Wall line | | background decor strokes only (bricks, lamps, posters, clouds, birds, skyline, railing). Never a fill |
| White | | default fill for everything: furniture, shirts, screens, pots, books, sneakers, mugs |
| Peach wood | | wood: ladder rails and boards, posts, stool, crate, a striped pot |
| Mustard | | one book, a duck, bulbs, sneakers, sticky notes, earring stud, a top |
| Orange | | a pot, trousers, a duck beak, shine arcs on brown hair, one code dash |
| Coral | | sneakers or soles, a label, a marker tip, a mug band, one code dash, window dot |
| Teal | | a book, a top, a mug band, a hammock stripe, a check mark |
| Sage / Leaf | | light and dark leaves, alternating leaf by leaf |
| Lavender | | a book, a top, page lines, keyboard lines, a sneaker sole |
| Purple | | a book, trousers, shine arcs on indigo hair, one code dash |
| Denim | | jeans |
| Brown | | brown hair, coffee in a cup |
| Skin | | light, medium, deep, dark; two people in a card get two different tones |
- Never: gradients, opacity, drop shadows, hatching, black, grey fills, the wall-line colour as a fill, a coloured background rect.
- One accent per object. A person wears at most two accents plus white: top, trousers, and sneakers where either the upper or the sole is white.
- No two large accent shapes of the same hue touch (a coral shoe on a coral rug). Keep the big shapes (shelf, board, desk, hammock) white or peach.
根据三个示例的实测结果(填充和描边,1x 渲染),白色与卡片本身约占全部像素的 85%,靛蓝线约占 2%,强调色占 4–7%。
| 角色 | Hex | 使用位置 |
|---|---|---|
| 靛蓝墨线 | | 所有轮廓线、地面线、眼睛点、靛蓝头发(头发为实心墨色形状) |
| 墙面色线 | | 仅用于背景装饰描线(砖块、吊灯、海报、云、鸟、天际线、栏杆),绝不作为填充色 |
| 白色 | | 所有内容的默认填充色:家具、衬衫、屏幕、花盆、书籍、运动鞋、马克杯 |
| 桃木色 | | 木质元素:梯架扶手和木板、立柱、凳子、板条箱、带条纹的花盆 |
| 芥末黄 | | 一本书、一只鸭子、灯泡、运动鞋、便利贴、耳钉、一件上衣 |
| 橙色 | | 花盆、裤子、鸭嘴、棕色头发上的高光弧线、一段代码短划线 |
| 珊瑚红 | | 运动鞋或鞋底、标签、马克笔笔尖、杯身色带、一段代码短划线、窗口圆点 |
| 蓝绿色 | | 一本书、一件上衣、杯身色带、吊床条纹、对勾 |
| 鼠尾草绿 / 叶绿色 | | 深浅叶片颜色,逐片交替使用 |
| 淡紫色 | | 一本书、一件上衣、书页线、键盘线、运动鞋底 |
| 紫色 | | 一本书、裤子、靛蓝头发上的高光弧线、一段代码短划线 |
| 牛仔蓝 | | 牛仔裤 |
| 棕色 | | 棕色头发、杯中咖啡 |
| 肤色 | | 浅色、中等肤色、深肤色、最深肤色;同一张卡片中的两个人使用两种不同色调 |
- 绝不使用:渐变、透明度、投影、排线、黑色、灰色填充、将墙面色线用作填充色、彩色背景矩形。
- 每个物体仅使用一种强调色。一个人除白色外最多使用两种强调色:上衣、裤子,以及鞋面或鞋底其中之一为白色的运动鞋。
- 不得让两个颜色相同的大型强调色形状相互接触,例如珊瑚红鞋子与珊瑚红地毯。大型形状(搁架、写字板、书桌、吊床)应保持白色或桃木色。
Line and fill
线稿与填充
- Two layers. Background: . Foreground:
<g id="xx-bg" fill="none" stroke="#cfc9e0" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">. Shapes inherit the stroke; each sets its own<g id="xx-fg" stroke="#3a2d66" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">.fill - Outlines are strokes on filled shapes, never filled outline shapes. Every foreground shape gets a fill (white if nothing else), so overlap hides what is behind. Depth comes only from overlap order: draw back to front, far limbs before the torso.
- Weights at 480 wide: 1.4 for every outline; 1 for detail lines (fabric folds, leaf veins, book bands, lace ticks, ear inner, brows, nose, mouth, steam, x marks, hair shine); 0.9 for finger separations; 1.2 for whiteboard diagram strokes; 1.7–1.8 coloured dashes for code on screens; 2.2 for bullet dots ().
M190 146h0.1 - Shading: none. No tone steps, no hatching, no highlights. A fold is one 1 px curve, 4–8 px long, 2–3 per garment.
- Texture: tiny x marks (, 3 px, stroke 1), 2–4 per pot or box. Never on clothing.
xm() - Lettering: , 4.4–5.2 px, 2–5 letters (JS, CSS, UX, API, CACHE) on a small label rect,
font-family="ui-monospace, monospace" font-weight="700".stroke="none" - Rounded corners: rx 0.6–1 on books and bricks, 1.5–2.5 on furniture tops and frames.
- 分成两层。背景:。前景:
<g id="xx-bg" fill="none" stroke="#cfc9e0" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">。形状会继承描边属性,每个形状自行设置<g id="xx-fg" stroke="#3a2d66" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">。fill - 轮廓必须是填充形状上的描边,绝不能使用填充出来的轮廓形状。每个前景形状都要有填充色;没有指定颜色时使用白色,以便通过重叠遮挡后方内容。景深仅依靠重叠顺序表现:先画后方,再画前方;远侧肢体先于躯干绘制。
- 在宽度为 480 时,所有轮廓线均为 1.4;细节线为 1(衣物褶皱、叶脉、书籍束带、鞋带刻度、耳内、眉毛、鼻子、嘴巴、蒸汽、叉号、头发高光);手指分隔线为 0.9;白板图示描边为 1.2;屏幕代码使用 1.7–1.8 的彩色短划线;圆点为 2.2()。
M190 146h0.1 - 不使用明暗塑造。不要色阶、排线或高光。衣物褶皱是一条长 4–8 px 的 1 px 曲线,每件衣服使用 2–3 条。
- 纹理:在花盆或箱子上使用微小叉号(,3 px,描边宽度 1),每个花盆或箱子放 2–4 个。绝不能放在衣物上。
xm() - 文字:,字号 4.4–5.2 px,在小型标签矩形上放置 2–5 个字母(JS、CSS、UX、API、CACHE),并设置
font-family="ui-monospace, monospace" font-weight="700"。stroke="none" - 圆角:书籍和砖块使用 0.6–1 的圆角,家具台面和画框使用 1.5–2.5 的圆角。
Characters
角色
- Proportions: a standing figure is 229–235 px from crown to sole; the head (chin to crown) is 33–36 px, so 1:7. Slim: shoulders about 30 wide, legs with hip half-width 9.6–11 tapering to 5.6–5.8 at the hem.
- Head: build it with from the toolkit. It draws a 3/4 profile facing left or right: one face path with the nose and chin in the contour, an ear on the back side, a near eye dot (r 1.15) and a far eye dot (r 1.0) 4.9 apart, two 1 px brows, a nostril tick and a short mouth arc. No cheek colour, no pupils, no open mouths. Calm, slightly smiling.
head() - Hair: one flat shape in indigo (1–4 shine arcs in purple
#3a2d66) or brown#7f6cc4(shine in orange#7b4b3a). Presets:#f6a85e,afro,bun,side(+crop,beard,glasses). The afro's back mass returns asearring: draw it before the torso.behind - rotates in screen degrees (+ = clockwise). That nods a right-facing head DOWN and a left-facing head UP. Tilt 4–9° toward what the person looks at.
head(x, y, rot, opts) - Neck and torso: draws the neck, a soft shirt shape 30–34 wide (crew-neck tee or fitted top with a small V collar) and two 1 px folds, all placed from the head centre.
torso(hx, hy, { style: 'tee' | 'top', facing, fill, skin })gives the shoulder, hip and waistband points relative to the head centre. Mirror their x for a left-facing figure. Tops are white or one accent.TORSO_ANCHORS[style] - Sleeves: caps the upper arm; drawn after the arm. A flatter sleeve (half-width under 6) avoids a shoulder-pad look.
sleeve(S, arm.u, 13, 5.8) - Arms: with half-widths 4.4–5 shoulder, 4–4.4 elbow, 3.2–3.4 wrist. It gives a pointed outer elbow; add the 3 px crease line from
bentArm(). Upper arm 27–40, forearm 24–33. Usearm.Iand try bothsolveElbow(S, wrist, 35, 30, flip)values: the right one hangs the elbow below the shoulder-to-wrist line. Keep the wrist 45–60 px from the shoulder. Closer, and the arm folds into a chicken wing.flip - Put a fingertip on a target with . It returns the wrist point to solve the arm to.
wristFor(HANDS[name].tip, target, angle, scale, flip) - The far arm in a profile view: show it. Swing it back behind the hip (or forward behind a held object), drawn before the torso, so a forearm and a hand show below the torso. A figure with one arm reads as "an arm is missing".
rest - Hands (toolkit ): 17 local units at scale 1.05–1.15, so 18–20 px long, about the face from chin to brow. Fingers are 3–4 rounded bands with 0.9 separation lines; the middle finger is longest, the little finger shortest. Shapes:
HANDS(palm down on keys),type(wrapped round a mug, thumb over the rim),cup(same, thumb hidden behind the object),wrap(fist round a pen, withmarker),HANDS.marker.pen()(index out, thumb tucked),point(relaxed).rest - Every hand shape has its thumb on local −y. Decide LEFT or RIGHT and PALM or BACK with the table in , then pass
references/craft.mdwhen the thumb belongs on +y.flip = true - Legs and feet: for standing legs (tapered, flat hem, 5.2 px rolled cuff band, 4–10 px of ankle skin);
trouserLeg()+bentLeg()for sitting or stepping.cuffAndAnkle()is 25 × 10.6 with a 3 px sole band and two lace ticks; heel at the floor point, mirrored withsneaker(). End each trouser leg at the shoe'sscale(-1 1).shoeOpening(heel, rot, mirror) - Rear foot on its toes: , then
heel = liftedHeel(toeX, 22–28, mirror)translate(heel) rotate(deg)`)sneaker(\rotate(-deg) scale(-1 1). For a mirrored shoe useshoeOpening(heel, -deg, true)`.and - Poses that work: reaching up to a shelf or board, or pressing a button, with the upper body leaning 4–9° (rotate the upper-body group about the hip and the shoulder points with ); the rear heel lifted so only the toe touches the floor; lying in a hammock with the laptop on the thighs; sitting on a stool, one foot on the rung, holding a cup.
rotAbout()
- 比例:站立人物从头顶到鞋底为 229–235 px;头部从下巴到头顶为 33–36 px,因此比例为 1:7。人物纤细:肩宽约 30;腿部臀点半宽为 9.6–11,向裤脚收窄至 5.6–5.8。
- 头部:使用工具包中的 绘制。它会绘制朝左或朝右的 3/4 侧面:一条包含鼻子和下巴轮廓的面部路径、后侧耳朵、近侧眼点(半径 1.15)和远侧眼点(半径 1.0),两眼相距 4.9;还包括两条 1 px 眉毛、一个鼻孔刻度和一段短嘴弧。不要脸颊颜色、瞳孔或张开的嘴,神情平静并略带微笑。
head() - 头发:使用一块扁平形状填充靛蓝色 (搭配 1–4 条紫色
#3a2d66高光弧线),或填充棕色#7f6cc4(搭配橙色#7b4b3a高光)。预设包括:#f6a85e、afro、bun、side(另有crop、beard、glasses)。earring的后侧发量作为afro返回,应在躯干之前绘制。behind - 按屏幕角度旋转(正数为顺时针)。这样会让朝右的头部向下点头,让朝左的头部向上抬起。向人物所关注的方向倾斜 4–9°。
head(x, y, rot, opts) - 颈部和躯干:绘制颈部、宽 30–34 的柔和上衣形状(圆领 T 恤或带小 V 领的修身上衣)和两条 1 px 褶皱;所有位置都以头部中心为基准。
torso(hx, hy, { style: 'tee' | 'top', facing, fill, skin })给出相对于头部中心的肩部、髋部和腰带位置。朝左人物需镜像这些点的 x 坐标。上衣应为白色或一种强调色。TORSO_ANCHORS[style] - 袖子:覆盖上臂,并在手臂之后绘制。使用较扁的袖子(半宽小于 6),避免产生垫肩效果。
sleeve(S, arm.u, 13, 5.8) - 手臂:的肩部半宽为 4.4–5、肘部为 4–4.4、腕部为 3.2–3.4。它会形成尖外侧肘部;再添加来自
bentArm()的 3 px 肘部褶皱线。上臂长 27–40,前臂长 24–33。使用arm.I,并尝试两个solveElbow(S, wrist, 35, 30, flip)值:正确的值会让肘部落在肩部至腕部连线的下方。腕部与肩部应保持 45–60 px 距离;距离过近会让手臂折成“鸡翅膀”。flip - 使用 将指尖放到目标位置。它会返回用于解算手臂的腕部坐标。
wristFor(HANDS[name].tip, target, angle, scale, flip) - 侧面视角也要画出远侧手臂。将其向后摆至臀部后方,或向前放在所持物体后方,并在躯干之前绘制,使前臂和 手型能从躯干下方露出。隐藏其中一只手臂会让人物看起来“少了一条胳膊”。
rest - 手部(工具包 ):在 1.05–1.15 的缩放下为 17 个本地单位,因此长 18–20 px,约等于从下巴到眉毛的脸部长度。手指由 3–4 条圆头指带组成,使用 0.9 的分隔线;中指最长,小指最短。手型包括:
HANDS(掌心向下放在键盘上)、type(环握马克杯,拇指搭在杯沿上)、cup(同样环握,但拇指藏在物体后方)、wrap(握笔成拳,并配合marker)、HANDS.marker.pen()(伸出食指,收起拇指)、point(自然放松)。rest - 每种手型的拇指都位于本地坐标的 −y 方向。根据 中的表格判断 LEFT 或 RIGHT,以及 PALM 或 BACK;当拇指应位于 +y 时传入
references/craft.md。flip = true - 腿和脚:站立腿部使用 (逐渐收窄、平直裤脚、5.2 px 卷边、露出 4–10 px 脚踝肤色);坐姿或迈步使用
trouserLeg()与bentLeg()。cuffAndAnkle()尺寸为 25 × 10.6,包含 3 px 鞋底色带和两条鞋带刻度;鞋跟位于落地点,并通过sneaker()镜像。每条裤腿都应结束于鞋子的scale(-1 1)。shoeOpening(heel, rot, mirror) - 后脚踮起:,然后使用
heel = liftedHeel(toeX, 22–28, mirror)translate(heel) rotate(deg)`)sneaker(\rotate(-deg) scale(-1 1)。镜像鞋子使用shoeOpening(heel, -deg, true)`。和 - 适用姿势:伸手够向搁架或写字板,或按下按钮;上半身围绕髋部倾斜 4–9°(使用 旋转上半身组及肩部坐标);后脚跟抬起,仅脚尖触地;躺在吊床中并将笔记本电脑放在大腿上;坐在凳子上,一只脚踩在横档上,同时拿着杯子。
rotAbout()
Decor and props
装饰与道具
- Background layer (wall line, unfilled), all of it pale and secondary: 2–3 brick clusters of 3–5 bricks (, 14 × 6, rows 7 apart), 1–2 pendant lamps hanging from the card's top edge (
bricks(),lampDome()), 1 framed poster on a nail (lampCone()) with a simple icon inside. Outdoors: 2–3 outline clouds, 2–3 birds, a skyline and a railing instead of bricks.poster() - Foreground, per card: one hero prop in the middle that carries the subject (ladder shelf 98 × 203, whiteboard on wheels 160 × 256, hammock between posts 260 wide); one tall plant in a pot at one end (60–68 wide, 150–185 tall); one secondary piece at the other end (desk with a monitor and mug, a short snake plant, a stool with a colleague); 2–4 small props (mug with two 1 px steam curls, books with band lines and labels, a rubber duck, sticky notes, a monitor with window dots and coloured code dashes).
- Plants: (lance leaves with veins),
leaf()(fiddle-leaf fig),figLeaf()(snake plant), stems as 1.4 px open curves from the pot, leaves alternating sage and leaf green. Pots:blade(), white with x marks, peach with 1 px bands, or orange.pot() - Never: sparkles, confetti, floating icons, speech bubbles, shadows under objects, rugs, more than two items on the floor beside the hero.
- 背景层使用墙面色线且不填充,所有元素都必须浅淡并处于次要位置:2–3 组砖块,每组 3–5 块(,14 × 6,行间距 7);1–2 盏从卡片顶边垂下的吊灯(
bricks()、lampDome());一幅用钉子挂在墙上的带框海报(lampCone()),内部配简单图标。户外场景改用 2–3 朵轮廓云、2–3 只鸟,以及天际线和栏杆,不使用砖块。poster() - 每张卡片的前景设置一个位于中央、承载主题的主道具(梯形搁架 98 × 203、带轮白板 160 × 256、支柱间宽 260 的吊床);一端放一盆高植物(宽 60–68,高 150–185);另一端放一个次要物件(带显示器和马克杯的书桌、矮蛇皮植物、与同事同坐的凳子);另加 2–4 个小道具(带两缕 1 px 蒸汽的马克杯、带束带线和标签的书籍、橡皮鸭、便利贴、带窗口圆点和彩色代码短划线的显示器)。
- 植物:(带叶脉的披针形叶片)、
leaf()(琴叶榕叶)、figLeaf()(蛇皮植物叶);茎使用从花盆伸出的 1.4 px 开放曲线,叶片在鼠尾草绿和叶绿色之间交替。blade() - 花盆:使用 ;可为带 x 标记的白色、带 1 px 色带的桃木色,或橙色。
pot() - 绝不使用:闪光点、彩纸、漂浮图标、对话气泡、物体下方的阴影、地毯,以及主道具旁超过两个地面物件。
Composition
构图
- No background rect: the card is white (the examples have none). If the host page is not white, add a square full-bleed rect first.
#ffffff - Floor line at y 308: . Every foot, pot, leg and caster stands on it. The band below (y 308–360) stays empty.
M56 308H424M40 308h10M430 308h10 - Content spans x 33–445. Only lamp cords touch an edge (the top). Everything else stays at y ≥ 25.
- Left to right: tall plant (x 33–121) | hero prop with the figure acting on it (x 115–335) | secondary furniture or plant (x 330–445). Mirror this freely, but keep the hero central.
- Figures: 94–190 px wide, 235 tall standing. One focal action, at the figure's hands.
- Density: about 10–14 foreground objects including plant leaves; generous white space between groups. Busy is wrong here.
- Group transforms the examples use: to nudge a whole figure;
translate(-8 0)on the upper-body group (neck, torso, head, sleeve) to lean it over the hips.rotate(-7 284 180)
- 不设置背景矩形:卡片为白色,示例中也没有背景矩形。如果宿主页面不是白色,应先添加一个铺满画面的 正方形矩形。
#ffffff - 地面线位于 y 308:。每只脚、花盆、腿部及脚轮都要落在地面上。下方 y 308–360 的区域保持空白。
M56 308H424M40 308h10M430 308h10 - 内容横跨 x 33–445。只有灯绳可以接触边缘(顶部);其他所有元素都保持在 y ≥ 25。
- 从左到右依次为:高植物(x 33–121)|承载人物动作的主道具(x 115–335)|次要家具或植物(x 330–445)。可以自由镜像,但主道具必须位于中央。
- 人物:宽 94–190 px,站立时高 235 px。画面中只保留一个焦点动作,并发生在人物手部所在的位置。
- 密度:前景约有 10–14 个物体,包括植物叶片;各组物体之间应留出大量空白。此风格不适合画面过于繁忙。
- 示例使用的组变换:使用 轻微移动整个人物;在上半身组(颈部、躯干、头部、袖子)上使用
translate(-8 0),让人物以髋部为支点前倾。rotate(-7 284 180)
Techniques
技巧
1. A parts toolkit. (no dependencies) has every repeated part with the examples' numbers: layers, floor, bricks, lamps, poster, cloud, leaves, pots, , , , , , , , , , , , , + + + , and . Run from the skill folder (write it into your work folder, not the skill) and render it to see every part. The demo output is a parts sheet: four heads, six hands with thumbs up, two plants, the lamps, the bricks and a standing figure built from the parts.
scripts/interior.mjslimbbentArmsolveElbowsleevetorsotrouserLegbentLegcuffAndAnklesneakershoeOpeningliftedHeelrotAboutHANDShand()place()wristFor()head()mirrorPath()node scripts/interior.mjs --demo /abs/work/demo.svgA complete figure, tested: a woman facing left points at a chart. Save it as next to your card, fix the import path, and run .
card.mjsnode card.mjsjs
import fs from 'node:fs';
import * as LI from '/abs/path/to/illustration-line-interior/scripts/interior.mjs';
const { W, C, SKIN, FL, P, f } = LI, id = 'sn-', sk = SKIN.medium;
const HC = [300, 102], A = LI.TORSO_ANCHORS.top, rel = q => [HC[0] - q[0], HC[1] + q[1]]; // facing left: mirror x
const LEAN = -5, PV = [300, 188]; // lean toward the left, about the hips
const h = LI.head(HC[0], HC[1], -4, { hair: 'bun', facing: 'left', skin: sk, hairColor: C.brown, earring: true });
const heelB = LI.liftedHeel(300, 24, true); // rear heel up, toe on the floor
const legF = LI.trouserLeg([[296, 188], [293, 230], [291, 270], [290, 291]], [10, 8, 6.2, 5.8], LI.shoeOpening([297, FL], 0, true), C.denim, sk);
const legB = LI.trouserLeg([[306, 188], [309, 230], [313, 262], [316, 282]], [10.6, 8.4, 6.4, 5.8], LI.shoeOpening(heelB, -24, true), C.denim, sk);
let fg = LI.floor(id);
fg += `<rect x="150" y="96" width="70" height="54" rx="2" fill="${W}"/><path d="M158 138l14-16 10 9 12-15 16 12" fill="none" stroke="${C.teal}" stroke-width="1.8"/>`;
fg += legB.skin + LI.sneaker(`translate(${P(heelB)}) rotate(-24) scale(-1 1)`, C.coral, W) + legB.leg;
fg += legF.skin + LI.sneaker(`translate(297 ${FL}) scale(-1 1)`, C.coral, W) + legF.leg;
fg += `<rect x="284" y="${HC[1] + A.waistTop}" width="33" height="5" rx="0.8" fill="${C.denim}"/>`;
fg += `<g transform="rotate(${LEAN} ${P(PV)})">${LI.torso(HC[0], HC[1], { style: 'top', facing: 'left', fill: C.lav, skin: sk })}${h.front}</g>`;
// near arm = LEFT (she faces left); back of the hand visible, index pointing left -> thumb UP.
// HANDS.point keeps its thumb on local -y; at 186 deg local -y points DOWN, so flip = true.
const S = LI.rotAbout(rel(A.nearShoulder), LEAN, PV), ang = 186, tip = [221, 124];
const Wr = LI.wristFor(LI.HANDS.point.tip, tip, ang, 1.1, true);
const arm = LI.bentArm(S, LI.solveElbow(S, Wr, 36, 30), Wr, 4.6, 4.2, 3.3);
fg += `<path d="${arm.d}" fill="${sk}"/><path d="M${P(arm.I)}l${f(-arm.u[0] * 3)} ${f(-arm.u[1] * 3)}" fill="none" stroke-width="1"/>`;
fg += `<path d="${LI.sleeve(S, arm.u, 13, 5.8)}" fill="${C.lav}"/>` + LI.place(LI.hand('point', sk), Wr[0], Wr[1], ang, true, id + 'hand', 1.1);
const bg = LI.bgLayer(id, LI.bricks(60, 80, [[0, 0], [15, 0], [7, 7]]) + LI.lampDome(380, 40));
fs.writeFileSync('card.svg', LI.svgWrap(bg + LI.fgLayer(id, fg), 'Snippet test, Line interior style'));It still needs the far arm, a plant, the hero prop and the room. It shows the order: legs → waistband → leaned torso and head → near arm → sleeve → hand.
2. Hands without a wrist wedge. Draw the hand outline twice: once filled with , once as an open path (the removed), then the 0.9 finger lines, then the thumb. does this. A closed stroke across the wrist draws a dark wedge where the forearm meets the hand.
stroke="none"Zhand()3. Lean by group rotation. Put the torso (with its neck), any backpack or strap and the head in one . Solve the arms in card coordinates from , so the hand still lands on the object, and draw the arm, sleeve and hand outside the group.
<g transform="rotate(-7 hipX hipY)">rotAbout(shoulder, -7, [hipX, hipY])4. Screen and board content in colour, not ink. Code on a monitor is 4–6 rows of round-capped dashes, , each dash one accent (purple, teal, coral, lavender, orange), on a white screen with three window dots (coral, mustard, teal, r 0.9). Diagrams are 1.2 px boxes and arrows in ink, one box in coral and one in teal.
stroke-width="1.8"1. 部件工具包。 不依赖任何外部包,并按照示例中的数值实现了所有重复部件,包括:图层、地面、砖块、吊灯、海报、云、叶片、花盆、、、、、、、、、、、、、 + + + 、 和 。在 skill 文件夹中运行 ,并渲染输出,即可查看所有部件。演示输出是一张部件表,包含四个头部、六种竖拇指手型、两种植物、吊灯、砖块,以及一个使用这些部件搭建的站立人物。
scripts/interior.mjslimbbentArmsolveElbowsleevetorsotrouserLegbentLegcuffAndAnklesneakershoeOpeningliftedHeelrotAboutHANDShand()place()wristFor()head()mirrorPath()node scripts/interior.mjs --demo /abs/work/demo.svg下面是一个经过测试的完整人物:一名朝左的人物指向图表。将代码保存为卡片旁的 ,修正 import 路径,然后运行 。
card.mjsnode card.mjsjs
import fs from 'node:fs';
import * as LI from '/abs/path/to/illustration-line-interior/scripts/interior.mjs';
const { W, C, SKIN, FL, P, f } = LI, id = 'sn-', sk = SKIN.medium;
const HC = [300, 102], A = LI.TORSO_ANCHORS.top, rel = q => [HC[0] - q[0], HC[1] + q[1]]; // facing left: mirror x
const LEAN = -5, PV = [300, 188]; // lean toward the left, about the hips
const h = LI.head(HC[0], HC[1], -4, { hair: 'bun', facing: 'left', skin: sk, hairColor: C.brown, earring: true });
const heelB = LI.liftedHeel(300, 24, true); // rear heel up, toe on the floor
const legF = LI.trouserLeg([[296, 188], [293, 230], [291, 270], [290, 291]], [10, 8, 6.2, 5.8], LI.shoeOpening([297, FL], 0, true), C.denim, sk);
const legB = LI.trouserLeg([[306, 188], [309, 230], [313, 262], [316, 282]], [10.6, 8.4, 6.4, 5.8], LI.shoeOpening(heelB, -24, true), C.denim, sk);
let fg = LI.floor(id);
fg += `<rect x="150" y="96" width="70" height="54" rx="2" fill="${W}"/><path d="M158 138l14-16 10 9 12-15 16 12" fill="none" stroke="${C.teal}" stroke-width="1.8"/>`;
fg += legB.skin + LI.sneaker(`translate(${P(heelB)}) rotate(-24) scale(-1 1)`, C.coral, W) + legB.leg;
fg += legF.skin + LI.sneaker(`translate(297 ${FL}) scale(-1 1)`, C.coral, W) + legF.leg;
fg += `<rect x="284" y="${HC[1] + A.waistTop}" width="33" height="5" rx="0.8" fill="${C.denim}"/>`;
fg += `<g transform="rotate(${LEAN} ${P(PV)})">${LI.torso(HC[0], HC[1], { style: 'top', facing: 'left', fill: C.lav, skin: sk })}${h.front}</g>`;
// near arm = LEFT (she faces left); back of the hand visible, index pointing left -> thumb UP.
// HANDS.point keeps its thumb on local -y; at 186 deg local -y points DOWN, so flip = true.
const S = LI.rotAbout(rel(A.nearShoulder), LEAN, PV), ang = 186, tip = [221, 124];
const Wr = LI.wristFor(LI.HANDS.point.tip, tip, ang, 1.1, true);
const arm = LI.bentArm(S, LI.solveElbow(S, Wr, 36, 30), Wr, 4.6, 4.2, 3.3);
fg += `<path d="${arm.d}" fill="${sk}"/><path d="M${P(arm.I)}l${f(-arm.u[0] * 3)} ${f(-arm.u[1] * 3)}" fill="none" stroke-width="1"/>`;
fg += `<path d="${LI.sleeve(S, arm.u, 13, 5.8)}" fill="${C.lav}"/>` + LI.place(LI.hand('point', sk), Wr[0], Wr[1], ang, true, id + 'hand', 1.1);
const bg = LI.bgLayer(id, LI.bricks(60, 80, [[0, 0], [15, 0], [7, 7]]) + LI.lampDome(380, 40));
fs.writeFileSync('card.svg', LI.svgWrap(bg + LI.fgLayer(id, fg), 'Snippet test, Line interior style'));这段代码仍需补充远侧手臂、植物、主道具和房间。它展示的绘制顺序为:腿部 → 腰带 → 倾斜的躯干和头部 → 近侧手臂 → 袖子 → 手部。
2. 手腕处不出现深色楔形。 将手部轮廓绘制两次:第一次填充并设置 ,第二次绘制移除 的开放路径;然后添加 0.9 的手指分隔线,最后绘制拇指。 已实现这一过程。横跨手腕的闭合描边会在前臂与手部连接处形成深色楔形。
stroke="none"Zhand()3. 通过组旋转实现倾斜。 将躯干(连同颈部)、背包或背带以及头部放入同一个 中。使用 在卡片坐标系中解算手臂,使手部仍能准确落在目标物体上;手臂、袖子和手部应绘制在该组之外。
<g transform="rotate(-7 hipX hipY)">rotAbout(shoulder, -7, [hipX, hipY])4. 屏幕和写字板内容使用彩色,而不是墨线。 显示器中的代码由 4–6 行圆头短划线组成,描边宽度为 ,每条短划线使用一种强调色(紫色、蓝绿色、珊瑚红、淡紫色、橙色)。屏幕为白色,并带有三个窗口圆点(珊瑚红、芥末黄、蓝绿色,半径 0.9)。图示使用 1.2 px 的墨线方框和箭头,其中一个方框为珊瑚红,另一个为蓝绿色。
1.8Failure modes
常见失败模式
- Too much colour. The first Books draft (scored 6) had a mustard top, a brown shelf, an orange pot and x marks on the clothes. The redraw that reached 8 used colour more sparingly. Keep big shapes white or peach, and accents under 7% (white ≥ 83%).
- The subject reads as something else. A developer standing at a desk read as "standing desk", not "Books". The figure must do the subject: pull the book off the shelf, draw on the board.
- Bolt-upright clip-art figure. Lean the upper body 4–9°, put the weight on one leg, lift the rear heel. Front-facing symmetric poses score a point lower.
- Dark wedge at the wrist. A closed outline across the wrist. Use (fill pass plus open outline).
hand() - Thumb on the wrong side. Two shipped hands were copies of a right-hand template on a left arm (Remote Work's far typing hand, Whiteboard's mug hand), and both had to be mirrored. Work out handedness per hand, then .
flip - Mitten or rake hands. Fingers must be grouped bands of different lengths with rounded tips, 18–20 px long. Larger reads as a glove.
- Arm with no elbow. A straight tube from shoulder to object reads as a prosthetic. Use and the crease line.
bentArm() - Chicken-wing arm. The target sat 33 px from the shoulder, so a 66 px arm folded up with the elbow out. Move the prop or the figure until the wrist is 45–60 px from the shoulder, and try the other .
flip - One-armed figure. A profile figure with the far arm hidden reads as missing an arm. Swing the far arm back so its forearm and hand show behind the hip.
- Stray ticks. A 1 px fold line within 4 px of a limb's edge, or a strap end poking 2 px out from under a sleeve, reads as a slip. End a covered shape at least 3 px inside the shape that covers it, and keep folds away from other contours.
- Floating feet or pots. Sneaker heels sit at y 308 exactly. A rotated rear shoe touches the floor with its toe. Check every contact at 8x.
- X marks on clothes. They read as stains. Keep them on pots and boxes.
- Background competing with the figure. Decor drawn in indigo or filled looks like foreground clutter. It is wall-line , 1 px, unfilled, and sits at least 8 px clear of the figure's head.
#cfc9e0 - Weight drift. A 2 px outline or a 0.6 px detail breaks the style at once. Use exactly 1.4, 1 and 0.9.
- 颜色过多。 第一版 Books 草稿评分为 6,其中包含芥末黄上衣、棕色搁架、橙色花盆,以及衣物上的 x 标记。重新绘制后评分为 8,颜色的使用明显更克制。大型形状应保持白色或桃木色,强调色面积低于 7%(白色至少占 83%)。
- 主体被误读。 一名站在桌旁的开发者看起来像“站立式书桌”,而不是“Books”。人物必须直接完成主体动作,例如从书架上取下书籍,或在白板上绘制内容。
- 人物像直立卡通剪贴画。 上半身应倾斜 4–9°,重心放在一条腿上,并抬起后脚跟。正面对称的姿势评分会低 1 分。
- 手腕处出现深色楔形。 这是跨手腕闭合轮廓造成的。应使用 ,即填充层加开放轮廓层。
hand() - 拇指方向错误。 已发布版本中的两只手都是右手模板的复制品,却被放在左臂上,即 Remote Work 的远侧打字手和 Whiteboard 的拿杯手,两者最终都必须镜像。应逐只手判断左右手和手心朝向,再设置 。
flip - 手像连指手套或耙子。 手指必须是长度各异的 3–4 组圆头指带,整体长 18–20 px。尺寸过大会看起来像手套。
- 手臂没有肘部。 从肩膀直伸到物体的管状手臂会像义肢。应使用 ,并添加肘部褶皱线。
bentArm() - “鸡翅膀”手臂。 目标距离肩膀仅 33 px,导致长 66 px 的手臂向上折叠、肘部向外突出。应移动道具或人物,使腕部与肩部保持 45–60 px 距离,并尝试另一个 值。
flip - 人物只有一只手臂。 侧面人物若隐藏远侧手臂,会显得缺少一条手臂。应将远侧手臂向后摆动,让前臂和手部从臀部后方露出。
- 出现游离刻线。 距离肢体边缘不足 4 px 的 1 px 褶皱线,或从袖子下方伸出 2 px 的背带末端,都会看起来像绘制失误。被遮挡的形状至少应缩入遮挡物内部 3 px,并让褶皱远离其他轮廓。
- 脚或花盆悬空。 运动鞋鞋跟必须准确位于 y 308。旋转的后脚应通过脚尖接触地面。应在 8x 放大图中检查所有接触点。
- 衣物上出现 x 标记。 这些标记看起来像污渍。只能将其放在花盆和箱子上。
- 背景与人物争夺注意力。 使用靛蓝色或填充状态的背景装饰会看起来像前景杂物。背景必须采用 1 px 的墙面色线 、不得填充,并且与人物头部至少保持 8 px 距离。
#cfc9e0 - 线宽漂移。 2 px 的轮廓或 0.6 px 的细节线会立即破坏风格。必须严格使用 1.4、1 和 0.9。
Examples
示例
- : "Books". A reaching pose with a −7° lean and a bent near arm gripping a book on the shelf (thumb on top). The far hand holds an open book at the hip. Afro back hair is drawn behind the torso. Ladder shelf with labelled books, a duck, a desk with a monitor, lance-leaf plant.
examples/books.svg - : "Remote Work". Lying in a hammock with both hands on a laptop (
examples/remote-work.svghands, mirrored for left and right). Outdoor variant of the background (clouds, birds, skyline, railing), string lights, a crate with a mug, monstera leaves, a snake plant. Atypehides the legs behind the hammock rim.clipPath - : "Whiteboard". Two people: one reaching up with a
examples/whiteboard.svgfist and amarkerhand on a mug, one seated on a stool with awraphand, beard and glasses. Diagram content in 1.2 px ink and accent strokes, sticky notes, casters on the floor line, fig plant.cup
- :“Books”。人物以 −7° 前倾,近侧手臂弯曲并抓住搁架上的一本书,拇指朝上。远侧手在臀部位置拿着打开的书。
examples/books.svg后侧发型绘制在躯干后方。场景包含带标签书籍的梯形搁架、一只鸭子、带显示器的书桌和披针形叶片植物。afro - :“Remote Work”。人物躺在吊床中,双手放在笔记本电脑上,使用镜像的
examples/remote-work.svg手型。背景采用户外版本,包含云、鸟、天际线和栏杆,并加入串灯、板条箱、马克杯、龟背竹叶和蛇皮植物。使用type将腿部隐藏在吊床边缘后方。clipPath - :“Whiteboard”。两个人物:一人伸手向上,使用
examples/whiteboard.svg拳型手部,另一只手使用marker手型拿着马克杯;另一人坐在凳子上,使用wrap手型,并留有胡须和眼镜。图示内容采用 1.2 px 墨线和强调色描边,场景还包括便利贴、脚轮和琴叶榕。cup
Workflow
工作流程
Run every command from this skill's folder. Card paths can be absolute.
- Brief. Name the subject in a few words and write the one action that shows it (who does what to which prop). Pick the hero prop and the pose.
- Plan the layout on the 480 × 360 grid: floor y 308, plant at one end, hero prop centred, secondary piece at the other end. Pick the skin tones, hair presets and the 2 accents each person wears. Choose an id prefix ().
ob- - Write a generator () that imports
card.mjsby absolute path and writesscripts/interior.mjs. Start from the Techniques snippet. Look at thecard.svgparts sheet once. Hand-place the figure and the hero prop; take everything repeated from the toolkit. Print the solved shoulder, elbow and wrist points so you can find them when you zoom.--demo - Hands first, on paper. For each hand, write down LEFT or RIGHT, PALM or BACK, and the finger direction, then the thumb side (see ). Choose the
references/craft.mdshape andHANDS.flip - Render: .
node scripts/render.mjs card.svg card.png - Sheet with the examples: . Ask "same hand, same set?": line weight, white share, density, floor, decor.
node scripts/render.mjs --sheet sheet.png examples/books.svg examples/remote-work.svg examples/whiteboard.svg card.svg - Zoom every hand, face, foot and contact: . Do the thumb proof from
node scripts/render.mjs card.svg z-hand.png --zoom x,y,w,h --scale 8for every hand.references/craft.md - Critique against the five criteria in and the Verify list below. Fix, re-render, re-sheet. Expect four or more rounds.
references/craft.md - Lint: . Fix every ERROR. Each WARN must be a deliberate tint.
node scripts/lint.mjs card.svg --prefix ob- --palette style.json
所有命令都在此 skill 的文件夹中运行。卡片路径可以使用绝对路径。
- 简报。 用几个词命名主题,并写出一个能够展示主题的动作,即谁对哪个道具做什么。选择主道具和姿势。
- 规划布局。 在 480 × 360 网格上进行规划:地面位于 y 308,一端放植物,中央放主道具,另一端放次要物件。选择肤色、发型预设,以及每个人使用的两种强调色。确定 id 前缀()。
ob- - 编写生成器。 创建 ,通过绝对路径导入
card.mjs,并输出scripts/interior.mjs。以上述技巧代码片段为起点。查看一次card.svg部件表。手工安排人物和主道具的位置;所有重复部件都从工具包中获取。输出解算后的肩部、肘部和腕部坐标,以便放大时查找。--demo - 先在纸上确定手型。 对每只手记录 LEFT 或 RIGHT、PALM 或 BACK、手指方向和拇指所在侧,参见 。选择
references/craft.md手型及HANDS。flip - 渲染。 运行 。
node scripts/render.mjs card.svg card.png - 与示例生成对比表。 运行 。检查“手型和整体风格是否一致?”,包括线宽、白色占比、密度、地面线和装饰。
node scripts/render.mjs --sheet sheet.png examples/books.svg examples/remote-work.svg examples/whiteboard.svg card.svg - 放大检查。 逐一检查手部、面部、脚部和接触点:。按照
node scripts/render.mjs card.svg z-hand.png --zoom x,y,w,h --scale 8对每只手执行拇指朝向验证。references/craft.md - 批评与修正。 根据 中的五项标准及下方验证清单进行检查。修正后重新渲染并重新生成对比表。预计需要四轮或更多迭代。
references/craft.md - Lint。 运行 。修复所有 ERROR。每条 WARN 都必须对应有意的色调选择。
node scripts/lint.mjs card.svg --prefix ob- --palette style.json
Verify
验证清单
- Every foreground outline is at 1.4; details are 1, finger lines 0.9; no other weights apart from code dashes (1.8) and diagram strokes (1.2).
#3a2d66 - Background decor is , 1 px, unfilled, and never overlaps a head.
#cfc9e0 - On the sheet, the colour looks no heavier than the examples (they measure 84–86% white pixels, accents 4–7%). The big shapes are white or peach, and nothing uses a gradient, opacity or shadow.
- Floor line at y 308 with both end dashes, and every foot, pot, leg and caster touches it.
- Lamps hang from y 0; nothing else touches a card edge; the y 308–360 band is empty.
- A standing person is about 230 px tall with a head about 34 px (1:7).
- Each person wears at most two accents plus white; two people have different skin tones.
- Every hand is 18–20 px long, has 3–4 grouped fingers with 0.9 separation lines, and its thumb is on the side the craft table gives (thumb proof done).
- Every arm has a shoulder, a pointed elbow with a crease, and a wrist narrower than the hand. Both arms show, even in profile.
- The upper body leans or twists; the weight is on one leg or on a seat.
- The subject reads at 1x from the figure's action alone, without the labels.
- No x marks on clothing; 2–4 on pots or boxes at most.
- passes with no unexplained WARN.
lint.mjs --palette style.json
- 所有前景轮廓均为 1.4 的 ;细节线为 1,手指线为 0.9;除代码短划线 1.8 和图示描边 1.2 外,不使用其他线宽。
#3a2d66 - 背景装饰使用 1 px、未填充的 ,且绝不与人物头部重叠。
#cfc9e0 - 在对比表中,色彩的视觉重量不超过示例水平;示例的白色像素占 84–86%,强调色占 4–7%。大型形状为白色或桃木色,不使用渐变、透明度或阴影。
- 地面线位于 y 308,并带有两端短划线;每只脚、花盆、腿部和脚轮都与其接触。
- 吊灯从 y 0 垂下;其他元素不接触卡片边缘;y 308–360 区域保持空白。
- 站立人物高约 230 px,头部高约 34 px,比例为 1:7。
- 每个人除白色外最多使用两种强调色;两个人使用不同肤色。
- 每只手长 18–20 px,包含 3–4 组手指和 0.9 的分隔线,拇指方向符合工艺表,并通过拇指朝向验证。
- 每条手臂都有肩部、带褶皱线的尖肘部,以及比手部更细的腕部。即使是侧面视角,也要显示两条手臂。
- 上半身有倾斜或扭转;重心落在一条腿上或座位上。
- 在 1x 尺寸下,仅凭人物动作就能读懂主体,无需依赖标签。
- 衣物上没有 x 标记;花盆或箱子上最多放 2–4 个。
- 通过检查,且没有无法解释的 WARN。
lint.mjs --palette style.json