算法艺术创作
algorithmic-art
通过代码和可调参数创作生成艺术与交互式视觉效果。
illustration-one-line【设计与创意】Draws original hand-written SVG spot illustrations in the One-line style, joyful action figures doing design and coding work. One continuous uniform black line (2.3 px at 480 wide) loops and doubles back to draw the whole figure. Flat coral, periwinkle and white patches sit behind the line, wobbly and deliberately knocked 2–6 px out of register like …
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
A loose, energetic style: a figure in mid-action drawn as one long wandering black line, with colour laid underneath as offset patches, as if a second print colour slipped. It suits upbeat product moments (launches, sprints, flow, celebrations) where an interior scene would be too heavy.
Use illustration-halftone-line for black open line with dot-screen tones and no colour. Use illustration-ink-sketch for a wobbly brush outline around a cute critter. Use illustration-two-colour-brush for thick brush outlines with solid black shapes and one mint ink.
Extracted from a set of 42 original design-and-coding cards in 14 styles; the three cards in examples/ are this style's shipped cards.
One continuous black line draws the whole figure, and flat coral, periwinkle and white patches sit behind it, deliberately knocked 2–6 px out of register.
Measured from the three examples (1x renders): paper 87–89% of the pixels, ink about 2%, white patches about 3%, periwinkle 2.3–3.7%, coral 0.8–2.8%.
| Role | Hex | Where it goes |
|---|---|---|
| Paper | #ece7da | full-bleed background rect, square, no rx |
| Ink | #1d1b1a | the one line, every prop line, code glyphs, speed strokes, the eye, solid dots |
| Coral | #f2846e | face and hand patches, stripe lines on tops, a sun, one accent patch per prop, code dashes |
| Periwinkle | #8790f4 | trousers, hair, screens and props, ground patches, code dashes |
| White | #ffffff | tops and sleeves, shoes, cups, clouds, ground patches |
#fff and #000 inside <mask> only; they never show.<g id="xx-ink" fill="none" stroke="#1d1b1a" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round">. Every ink path inherits it.</>); coral stripe lines 1.9; coded colour dashes 2.3.id="xx-figure") of smooth cubic segments, 1-decimal coordinates. Separate short strokes are allowed only for the eye, a hem or cuff, and props. Each prop is its own single wandering line too.[x, y] or [x, y, k] with tension k (1 smooth, 0.4–0.6 soft corner at elbows, knees and collars, 0 sharp for glyph corners).<g id="xx-patches">, then stripes and dashes in <g id="xx-accents">, then the ink on top.T(pts, dx, dy)), and wobble its edge (wobble, amp 0.8–1.5 for hands and faces, 1.4–2.4 for limbs, 2.2–3 for big areas). Use a different integer seed per patch. Let patches fall short of one side and spill past the other.<mask> holding the front shape's silhouette in black. Add a black stroke of 2–10 px to open a gap. C.mask() builds it.FACE_R (chin, lips, nose, brow as soft corners), over the crown and hair, down a ROUND back of the skull to the nape. Or the reverse, rev(FACE_R). The EAR_R C-loop is optional. Drop it if it doesn't read at 8x: an ear plus a flat hairline made a test head read as a helmet. The eye is a separate short closed-lid arc (EYE_R) and there is no mouth stroke (the profile carries the smile). A coral face patch covers the front half of the face, offset 1–2 px toward the profile, and leaves the back of the head bare paper.curls(), r 3–3.5, 4–5 loops) with no patch.blob() from the arm centreline.tube(centreline, widths) and route DOWN one side, round the hand or shoe, and back UP the other side. Put tension 0.4–0.6 on the elbow or knee point so it bends crisply. Keep a gripping wrist 45–60 px from its shoulder: a handle 48 px from the shoulder folded a test arm into a chicken wing (forearm 15 px, upper arm 33).shape.slice(1)) or shift the shape 3–4 px.C.mask('m-rider', [[route, 5]])). For that, start and end the route at the same place, such as the heel.HAND.mitten (swinging, thumb notch), HAND.fist (round a handle, knuckle bumps), HAND.tray (open palm carrying something), HAND.open (catching, thumb hooked out), spreadHand() (waving, four separate finger loops and a thumb), CLAMP (fist from the side gripping an edge). Never a plain oval.references/craft.md, then flip the shape (place(..., flip)) so its thumb lobe lands on that side. The comment above each shape in scripts/oneline.mjs says which side its thumb is on.SHOE loops, 30–35 px long (× 1.25–1.3), with a white patch, offset 3–4 px. A small heel loop is allowed on one shoe.loopAt(), cornerLoop()). More reads as scribble. A loop in the middle of a leg reads as a mistake.rot()) before routing.{ }, a laptop with </>, a stopwatch, a coffee cup, a bug, a sun drawn as a loading ring. Props tie into the motion: a squiggle trails into a stopwatch, one looping path threads the juggled objects.</> glyphs in 1.8 px ink on a screen or baton, and "code" as rows of coral and periwinkle squiggle dashes (squig(), 2.3 px).<rect id="xx-paper" x="0" y="0" width="480" height="360" fill="#ece7da"/> first. Then <defs> (masks), patches, accents, ink.makeCard('sd-', { map: pts => … }) applies it to every line, patch, accent, mask and dot (scale 1.05–1.1 about a centre, plus a shift). To face the other way, mirror x in the map (map: pts => mirrorX(pts, 240)), and draw </> glyphs and any lettering with C.raw.line(...), which skips the map, so they don't mirror.1. The toolkit. scripts/oneline.mjs (no dependencies, seeded) holds the curve maths and the card assembly: smooth, tube, blob, wobble, place, T, rev, rot, lowest, curls, squig, loopAt, cornerLoop, arc, the local shapes (HAND.*, spreadHand(), CLAMP, SHOE, FACE_R, EYE_R, EAR_R) and makeCard(prefix, { map }) with line, accent, patch, mask, dot (all mapped), raw.* (the same, unmapped), dots (debug) and svg(debug, ariaLabel). Patches and lines share one id namespace, so name patches after their colour (porthole-peri, shoe-white): a test card failed lint with two porthole ids. Run node scripts/oneline.mjs --demo /abs/work/demo.svg from the skill folder (write it into your work folder, not the skill) and render it: an arm with a mitten, a leg with a shoe on a ground squiggle, a profile head, patches, a stripe and code dashes.
2. A limb route. Down the R side, round the hand, back up the L side:
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);
Local shapes run from their +y wrist corner, round the tip, to the −y corner. Going down a limb's L side instead, use rev(shape) or flip = true.
3. Knock-out masks. const m = C.mask('m-arm', [[armSilhouettePts, 2]]); C.line('laptop', lapPts, m); hides the laptop's line under the arm. For a path that threads several objects, pass each object's silhouette with stroke 9–10 so the path stops short of them with a gap.
4. Ground the planted foot. const sole = lowest(route); then draw the squiggle at sole[1] + 1.1 with T(pts, sole[0], sole[1] + 1.1). A foot meant to stand must sit on it, not float above.
5. A whole-figure route order (the sprinter in examples/hackathon-sprint.svg, authored facing right). Every contour is visited once:
ground squiggle behind → planted shoe top → front of the trailing leg up → crotch → lead leg underside → lead shoe → shin front → knee → thigh top into the belly → far arm underside → fist → far arm top → shoulder → short neck → FACE_R → crown → ponytail → back of the skull → ear → nape → near arm top → mitten → near arm underside → armpit → back → waistband loop → seat → back of the trailing leg → heel loop → sole → toe → ground squiggle ahead.
A seated rider runs heel → calf → thigh underside → seat → back → raised arm → hand → nape → skull → bun loop → rev(FACE_R) → throat → near arm → fist → belly → thigh top → shin → shoe → back to the heel.
6. Patch recipe (offsets T(dx, dy), wobble amp, from the examples' generators). Top: the chest outline, (−4, −3), amp 2.4–2.6. Sleeves: blob(arm.slice(0, 3), W, 0.95–1.05), (±2–3, −3), amp 1.4–1.6. Trousers: blob(leg, W, 1.0), (5, 3), amp 2.2–2.4. Face: head-local [[6,-12],[16,-8],[22,2],[19,13],[9,15],[5,2]], (2, −1), amp 1.1–1.5. Hair: (−3, −2), amp 1.2–1.6. Hands: a 5–6 point blob of the hand, (2–3, ±2–3), amp 0.8–1.2. Shoes: [[-6,-2],[10,-3],[22,3],[22,10],[4,11],[-7,8]] through the shoe's own place(), (3–4, 2–3), amp 1.2. Props: (3–5, ±3), amp 1–1.8. Every seed different.
</> baton plus a stopwatch don't say "hackathon". Don't copy that card's head or back foot, and give the subject a prop that names it.lowest() and place the squiggle 1.1 px under it.examples/flow-state.svg: "Flow State". A leap with one arm flung back (spreadHand-style open hand) and the near arm clamping a laptop (CLAMP, masked). Curly hair from curls(), headphones, two code braces drawn as single strokes with white patches, code dashes, a sun as a loading ring, speed strokes, a trail squiggle.examples/hackathon-sprint.svg: "Hackathon Sprint". A sprint facing left: the figure is authored facing right and mirrored in G, with </> drawn in card space. A fist round a baton (masked), a swinging mitten, a ponytail, a waistband loop, a stopwatch tied into a squiggle, speed strokes. The weakest card: see Failure modes.examples/juggling-tasks.svg: "Juggling Tasks". Balancing on one leg with a tray hand under a laptop and an open hand just releasing. One looping motion path threads a cup and a bug (masked with stroke 9–10), a short ground squiggle with a periwinkle patch, a bun loop.Run every command from this skill's folder. Card paths can be absolute.
sd-).card.mjs) that imports scripts/oneline.mjs by absolute path. Build tubes, place hands and shoes, and write ONE route for the figure: start at a free end (a hand, a foot or a ground squiggle), go round every limb, and end at another free end. Render with C.svg(true) to see numbered route points while you work.references/craft.md). Pick the shape and the flip.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. Ask "same hand, same set?": line weight, how loose, patch offsets, density, paper share.node scripts/render.mjs card.svg z.png --zoom x,y,w,h --scale 8. Do the thumb proof from references/craft.md. The hands live inside the one route, so you can't recolour them. Instead, in a throwaway copy, put a red circle (r 2.2) on the thumb tip and a blue one on the index tip, both mapped through the same place() call, then delete the copy.references/craft.md and the Verify list. Fix, re-render, re-sheet. Four or more rounds is normal.node scripts/lint.mjs card.svg --prefix sd- --palette style.json.#ece7da full-bleed, no rx; only paper, ink, coral, periwinkle and white appear.<path>; apart from it there are only the eye, hems, props, speed strokes and squiggles.lint.mjs --palette style.json passes with no ERROR or WARN.