geomotion 是做什麼的?
geomotion turns a JSON spec — a list of keyframes, each a list of shapes — into a hand-drawn
animation. Shapes with the same id morph into each other between keyframes; lines keep
"boiling" (re-inked ~12×/s) so the result feels traced by hand.
Site & studio: https://hacimertgokhan.github.io/geomotion · Repo: https://github.com/hacimertgokhan/geomotion
Workflow
- Pick a route (use the first that is available):
- MCP tools (
geomotion_guide,geomotion_get_preset,geomotion_render,geomotion_share_link): callgeomotion_guideonce, then render. - CLI (Node 18+ with network):
npx -y github:hacimertgokhan/geomotion render spec.json --both --formats svg,lottie,html - No tooling: write the spec, then run
python scripts/link.py spec.json(in this skill folder) to get a player/studio link the user can open, edit and export from.
- MCP tools (
- Start from a preset when one is close (see catalog below) and adapt ids, positions, colours.
- Write the spec following the rules below. Validate (MCP
geomotion_validateorgeomotion check spec.json). - Deliver: file paths and/or the player link. Mention the studio link so they can tweak it. Offer a transparent version (
transparent: trueor"both") when the animation will sit on a website.
Spec essentials
{
"name": "idea",
"size": [1200, 1200],
"fps": 24, "boil": 12, "loop": true,
"background": "ivory",
"hold": 0.7, "duration": 0.9, "ease": "inOutCubic",
"style": { "width": 24, "wobble": 1, "misregister": [-14, 10] },
"keyframes": [
{ "shapes": [ { "id": "bulb", "type": "circle", "cx": 600, "cy": 520, "r": 220, "fill": "oat" } ] },
{ "hold": 1.2, "shapes": [
{ "id": "bulb", "type": "circle", "cx": 600, "cy": 520, "r": 240, "fill": "sun" },
{ "id": "ray", "type": "line", "from": [600, 200], "to": [600, 110], "enter": "draw", "delay": 0.3 }
] }
]
}
- Keyframe:
hold(seconds shown),duration(morph to the next keyframe),ease. - Shape types:
circle {cx,cy,r},ellipse {cx,cy,rx,ry},rect {x,y,w,h,radius?}or{cx,cy,w,h},line {from,to},polyline {points,closed?},polygon {points},regular {cx,cy,r,sides},triangle {cx,cy,r},star {cx,cy,r,inner?,points?},heart {cx,cy,size},blob {cx,cy,r,seed?},crescent {cx,cy,r,thickness?,angle?},wave {from,to,amplitude?,waves?,phase?},spiral {cx,cy,r,turns?},arc {cx,cy,r,start,end}(degrees, 0 = right, clockwise),path {d}(any SVG path). - Shape options:
id(match across keyframes — always set it),fill,stroke(colour orfalse),width,opacity,enter/exit(grow|pop|draw|fade|cut),delay(0–0.95, stagger),ease,transform {translate, rotate, scale, origin},misregister: falsefor tiny solid dots. - Palette names: ink, slate, ivory, paper, oat, kraft, clay, coral, fig, sky, cactus, olive, heather, sun, white (or any hex).
- Easings: linear, in/out/inOut Quad·Cubic·Sine, inOutQuart, outExpo, inOutExpo, outBack, inOutBack, outElastic, outBounce.
Design rules that make it look good
- 1200×1200 canvas, ~120 px margin, 2–5 bold shapes per pose. Small details read badly.
- Ink for every outline, one or two accent fills per pose (oat, clay, sun, sky, cactus, coral).
- Tell a story through ids: the same element transforms (sun → moon, envelope → paper plane, dot → heart).
- Stagger with
delay0 / 0.15 / 0.3; use"enter": "draw"for lines that should feel written,"pop"for playful arrivals. - Holds 0.5–1.2 s, morphs 0.5–1.2 s.
inOutCubic= calm,inOutBack/outBack= playful,outElastic= jelly. - Rotations > 30° between two keyframes make lines cut corners — split big rotations into several keyframes (see the
spinner,gears,orbitpresets). - Solid dots (eyes, typing dots):
"stroke": false, "fill": "ink", "misregister": false.
Preset catalog (start points)
- interface: loader, spinner, success, error, toggle, bell, search
- nature: sunrise, sprout, rain, night, sea
- communication: chat, send, like, connect
- ideas: idea, growth, target, gears, house
- characters: smile, ghost, sparkle
- abstract: drift, orbit, kaleido, pebbles
- motion: bounce, pendulum, jelly
Any preset opens directly: https://hacimertgokhan.github.io/geomotion/play/#preset=<name>
(add &bg=0 for a transparent background) or in the studio: /studio/#preset=<name>.
Embedding on a website
<script type="module" src="https://hacimertgokhan.github.io/geomotion/src/embed.js"></script>
<geo-motion preset="success" transparent style="width:160px"></geo-motion>
<geo-motion code="z…"></geo-motion> <!-- the #s=… part of a share link -->