{
  "schemaVersion": 1,
  "id": "stop-motion-feel",
  "version": "1.0.0",
  "status": "published",
  "kind": "motion",
  "title": "Stop-Motion Feel (Claymation)",
  "summary": "Makes any motion look hand-made frame by frame: pictures held at 12 a second, a tiny camera jitter, outlines that wobble, and clay shading with thumbprints under warm overcast light.",
  "description": "The claymation look taking over feeds in 2026, as motion you can apply to anything: time is held in steps like a stop-motion camera taking twelve pictures a second, each held picture gets a tiny camera shift, outlines boil from picture to picture, and shapes are shaded like matte clay with thumbprint dimples, a soft warm key and a cool rim from an overcast sky. The demo is a clay ball hopping past a stack of clay blocks on a felt table. Set the pictures per second, the jitter, the boil, the clay colours and the felt.",
  "role": "Timing and shading helpers for a handmade, stop-motion feel (Canvas 2D).",
  "collections": [
    "satisfying",
    "kinetic-text",
    "backgrounds"
  ],
  "tags": [
    "stop motion",
    "stop-motion",
    "claymation",
    "clay",
    "handmade",
    "12fps",
    "stepped",
    "jitter",
    "boil",
    "felt",
    "craft",
    "tactile",
    "cozy",
    "2d",
    "canvas"
  ],
  "synonyms": [
    "claymation effect",
    "stop motion look",
    "handmade animation",
    "clay animation",
    "frame by frame look",
    "stuttery animation",
    "cozy animation",
    "craft animation",
    "plasticine"
  ],
  "useCases": [
    "Cozy product or explainer clip",
    "Handmade-feeling title or sticker",
    "Giving a 2D scene a stop-motion rhythm"
  ],
  "featured": 2,
  "publishedAt": "2026-10-03",
  "implementation": {
    "target": "canvas2d",
    "runtime": "browser",
    "language": "javascript",
    "module": "esm",
    "entry": "src/stop-motion-feel.js",
    "exports": [
      {
        "name": "createStopMotion",
        "signature": "createStopMotion({ fps?, jitter?, boil?, seed? }) => { stepTime(info), hold(info, scale?) }",
        "description": "Holds time in pictures per second and gives a per-picture jitter and boil seed. Pure function of frame and seed."
      },
      {
        "name": "drawClay",
        "signature": "drawClay(ctx, { x, y, radius, width?, height?, corner?, color, squashX?, squashY?, boil?, boilSeed?, dimples?, seed? })",
        "description": "A lit clay ball or rounded block with thumbprints and a boiling outline."
      },
      {
        "name": "drawFelt",
        "signature": "drawFelt(ctx, { width, height, top?, color?, seed?, fibres? })",
        "description": "A felt table with fibre texture."
      },
      {
        "name": "clayPalette",
        "signature": "clayPalette: Record<string, string>",
        "description": "A few clay colours that read as handmade."
      }
    ],
    "reusable": [
      "src/stop-motion-feel.js"
    ],
    "demo": "demo.js",
    "harness": "index.html"
  },
  "dependencies": [
    {
      "id": "apw-runtime",
      "version": "1.0.0",
      "scope": "demo",
      "reason": "Demo harness and colour helpers. src/stop-motion-feel.js has no dependencies."
    }
  ],
  "params": [
    {
      "key": "fps",
      "label": "Pictures per second",
      "help": "12 is classic stop motion; 8 is chunkier; 24 is smooth.",
      "type": "integer",
      "min": 4,
      "max": 24,
      "step": 1,
      "default": 12
    },
    {
      "key": "jitter",
      "label": "Camera jitter",
      "help": "Pixels the whole picture shifts between held frames.",
      "type": "number",
      "min": 0,
      "max": 8,
      "step": 0.5,
      "default": 3
    },
    {
      "key": "boil",
      "label": "Outline wobble",
      "type": "number",
      "min": 0,
      "max": 2,
      "step": 0.1,
      "default": 1
    },
    {
      "key": "hops",
      "label": "Hops per clip",
      "type": "integer",
      "min": 2,
      "max": 8,
      "step": 1,
      "default": 4
    },
    {
      "key": "jump",
      "label": "Jump height",
      "type": "number",
      "min": 0.4,
      "max": 1.6,
      "step": 0.05,
      "default": 1
    },
    {
      "key": "seed",
      "label": "Variation",
      "type": "integer",
      "min": 1,
      "max": 9999,
      "step": 1,
      "default": 7
    },
    {
      "key": "colorA",
      "label": "Ball clay",
      "type": "color",
      "default": "#d9603a"
    },
    {
      "key": "colorB",
      "label": "Block clay 1",
      "type": "color",
      "default": "#8fae7a"
    },
    {
      "key": "colorC",
      "label": "Block clay 2",
      "type": "color",
      "default": "#e0a62a"
    },
    {
      "key": "felt",
      "label": "Felt",
      "type": "color",
      "default": "#b8a98c"
    },
    {
      "key": "background",
      "label": "Sky",
      "type": "color",
      "default": "#dfe6ea"
    }
  ],
  "presets": [
    {
      "id": "default",
      "label": "Terracotta hop",
      "params": {}
    },
    {
      "id": "chunky",
      "label": "Chunky 8 fps",
      "params": {
        "fps": 8,
        "jitter": 5,
        "boil": 1.6,
        "colorA": "#7fb3d9",
        "colorB": "#8c5a8f",
        "colorC": "#efe4cf",
        "felt": "#6f7f6a",
        "background": "#f1ece2"
      }
    },
    {
      "id": "smooth",
      "label": "Smooth & still",
      "params": {
        "fps": 24,
        "jitter": 0.5,
        "boil": 0.3,
        "hops": 3,
        "colorA": "#3a3238",
        "colorB": "#d9603a",
        "colorC": "#e0a62a",
        "felt": "#c9b99a"
      }
    }
  ],
  "output": {
    "width": 1080,
    "height": 1080,
    "fps": 30,
    "durationSeconds": 8,
    "posterSeconds": 1,
    "alpha": false,
    "motion": "procedural",
    "loop": {
      "seamless": true,
      "cycleSeconds": 8,
      "method": "Whole hops per clip and the ball crosses the table once per clip; held pictures, jitter and boil are functions of the held picture index, which wraps."
    },
    "seed": {
      "param": "seed",
      "behavior": "Same seed and settings give identical jitter, boil and thumbprints on every run."
    }
  },
  "composition": {
    "inputs": "Frame info; a seed.",
    "outputs": "Held time and a per-picture jitter to translate the canvas by; clay drawing helpers.",
    "coordinates": "Pixels. Call hold(info) once per frame, translate by jitterX/Y, then draw.",
    "lighting": "Shading assumes a soft key from the upper left and a cool rim lower right.",
    "timing": "hold() quantises time; feed its time (not info.time) to your motion for the stepped feel.",
    "compatibleWith": [
      "spring-motion",
      "kinetic-title",
      "gradient-background",
      "dither-animation"
    ],
    "notes": [
      "Apply hold() to a Three.js scene too: step the time you pass to your animation and offset the camera by the jitter.",
      "Keep fps whole and the clip duration a whole number of seconds so the held pictures divide the loop evenly."
    ]
  },
  "reuse": [
    "Feed hold(info).time into Spring Motion’s hop() for a clay character that bounces in held frames.",
    "Draw a Kinetic Title with drawClay blocks as letters for a handmade sticker title.",
    "Use drawFelt as a backdrop and the jitter alone to make any existing 2D scene feel shot on a tabletop."
  ],
  "integration": {
    "newProject": "createStopMotion once; each frame call hold(info), translate by the jitter, draw your scene with drawClay using the held time.",
    "existingProject": "Copy src/stop-motion-feel.js. Replace info.time with hold(info).time in your motion code and translate by the jitter before drawing."
  },
  "performance": {
    "notes": "Gradients per object; a few dozen objects are fine. drawFelt draws its fibres each frame; cache it to an offscreen canvas for big scenes.",
    "limits": "Canvas 2D only in this demo; the timing helper works anywhere."
  },
  "limitations": [
    "Clay shading is a 2D illusion (gradients), not a 3D material.",
    "Thumbprints and boil are random per held picture by seed, not sculpted detail."
  ],
  "license": {
    "spdx": "MIT",
    "notice": "Copyright (c) 2026 AI Pixel Wizard. Released under the MIT License. See LICENSE in this folder.",
    "thirdParty": []
  },
  "provenance": "Original code written for AI Pixel Wizard on 3 October 2026 by an automated agent, inspired by the claymation AI trend (OpusClip’s write-ups of claymation TikToks: 12 fps stutter, thumbprints, overcast light). No code, images or textures were copied.",
  "changelog": [
    {
      "version": "1.0.0",
      "date": "2026-10-03",
      "notes": "Initial release."
    }
  ]
}
