{
  "schemaVersion": 1,
  "id": "newtons-cradle",
  "version": "1.0.0",
  "status": "published",
  "kind": "object",
  "title": "Newton's Cradle",
  "summary": "Polished balls on a walnut base: one swings in, one swings out, click after click. Loops perfectly.",
  "description": "The classic executive toy on a glossy black table in a dark studio: a row of polished balls hung on V-shaped strings from two chrome rails, on a bevelled walnut base with brass feet. The end ball swings up and strikes the row, the far ball takes the motion and swings out, falls back and strikes again, the middle balls standing still, and so on. The balls mirror the studio and are mirrored in the table. Choose the finish of the balls (chrome, gold, black chrome or copper), the number of balls, whether one or two are lifted, how wide the swing is, how many clicks per loop, and the wood of the base.",
  "role": "Hero object (Three.js 3D): a satisfying, hypnotic desk toy for loops, intros and metaphors of cause and effect.",
  "collections": [
    "satisfying",
    "hypnotic-loops",
    "chrome-glass"
  ],
  "tags": [
    "newton's cradle",
    "pendulum",
    "desk toy",
    "chrome balls",
    "swinging balls",
    "momentum",
    "executive toy",
    "satisfying",
    "physics",
    "loop",
    "3d"
  ],
  "synonyms": [
    "newtons cradle",
    "clacking balls",
    "swinging spheres",
    "pendulum balls",
    "executive desk toy",
    "momentum balls",
    "kinetic toy",
    "balancing balls"
  ],
  "useCases": [
    "A satisfying loop for productivity, physics or office content",
    "A metaphor for cause and effect, momentum and chain reactions in explainers",
    "A calm, hypnotic backdrop behind a quote or a title"
  ],
  "featured": null,
  "publishedAt": "2026-10-06",
  "implementation": {
    "target": "three",
    "runtime": "browser",
    "language": "javascript",
    "module": "esm",
    "entry": "src/newtons-cradle.js",
    "exports": [
      {
        "name": "createNewtonsCradle",
        "signature": "createNewtonsCradle({ balls?, lift?, finish?, base?, amplitude?, seed?, anisotropy? }) => { group, height, count, update(time, loopSeconds, { cycles? }), dispose() }",
        "description": "The cradle as a THREE.Group (1 unit = 10 cm, base on y = 0). update(time, loopSeconds) swings the balls; cycles is the number of whole cycles per loop."
      },
      {
        "name": "cradleSwing",
        "signature": "cradleSwing(u) => { left, right }",
        "description": "The swing of the end balls at a position u in the cycle, in units of the amplitude (−1 … 1)."
      },
      {
        "name": "FINISHES",
        "signature": "FINISHES: { chrome, gold, black, copper }",
        "description": "Finishes for the balls."
      },
      {
        "name": "BASES",
        "signature": "BASES: { walnut, maple, ebony }",
        "description": "Finishes for the base."
      }
    ],
    "reusable": [
      "src/newtons-cradle.js"
    ],
    "demo": "demo.js",
    "harness": "index.html"
  },
  "dependencies": [
    {
      "id": "three",
      "version": "0.185.1",
      "reason": "Renderer, geometry and physical metals."
    },
    {
      "id": "chrome-material",
      "version": "1.1.0",
      "scope": "demo",
      "reason": "Studio environment light and backdrop."
    },
    {
      "id": "apw-runtime",
      "version": "1.0.0",
      "scope": "demo",
      "reason": "Demo harness."
    }
  ],
  "params": [
    {
      "key": "finish",
      "label": "Balls",
      "type": "select",
      "default": "chrome",
      "options": [
        {
          "value": "chrome",
          "label": "Chrome"
        },
        {
          "value": "gold",
          "label": "Gold"
        },
        {
          "value": "black",
          "label": "Black chrome"
        },
        {
          "value": "copper",
          "label": "Copper"
        }
      ]
    },
    {
      "key": "balls",
      "label": "Number of balls",
      "type": "integer",
      "min": 3,
      "max": 7,
      "step": 1,
      "default": 5
    },
    {
      "key": "lift",
      "label": "Balls lifted",
      "type": "integer",
      "min": 1,
      "max": 2,
      "step": 1,
      "default": 1
    },
    {
      "key": "swing",
      "label": "Swing (degrees)",
      "type": "number",
      "min": 20,
      "max": 48,
      "step": 1,
      "default": 36
    },
    {
      "key": "cycles",
      "label": "Clicks per loop",
      "help": "Whole cycles of the swing in each loop.",
      "type": "integer",
      "min": 1,
      "max": 6,
      "step": 1,
      "default": 4
    },
    {
      "key": "base",
      "label": "Base",
      "type": "select",
      "default": "walnut",
      "options": [
        {
          "value": "walnut",
          "label": "Walnut"
        },
        {
          "value": "maple",
          "label": "Maple"
        },
        {
          "value": "ebony",
          "label": "Black lacquer"
        }
      ]
    },
    {
      "key": "background",
      "label": "Studio",
      "type": "color",
      "default": "#13151b"
    },
    {
      "key": "seed",
      "label": "Seed",
      "help": "Changes the wood grain.",
      "type": "integer",
      "min": 1,
      "max": 999,
      "step": 1,
      "default": 3
    }
  ],
  "presets": [
    {
      "id": "default",
      "label": "Chrome on walnut",
      "params": {}
    },
    {
      "id": "gold",
      "label": "Gold on black, two lifted",
      "params": {
        "finish": "gold",
        "lift": 2,
        "balls": 6,
        "base": "ebony",
        "background": "#15110f",
        "cycles": 3
      }
    },
    {
      "id": "black",
      "label": "Black chrome on maple",
      "params": {
        "finish": "black",
        "base": "maple",
        "balls": 7,
        "swing": 32,
        "background": "#1b1e26"
      }
    },
    {
      "id": "copper",
      "label": "Copper, wide swing",
      "params": {
        "finish": "copper",
        "balls": 4,
        "swing": 44,
        "cycles": 2,
        "background": "#1a1311",
        "seed": 8
      }
    }
  ],
  "output": {
    "width": 1080,
    "height": 1080,
    "fps": 30,
    "durationSeconds": 9.6,
    "posterSeconds": 3.1,
    "alpha": false,
    "motion": "procedural",
    "loop": {
      "seamless": true,
      "cycleSeconds": 9.6,
      "method": "The swing repeats a whole number of cycles per loop, and a cycle starts and ends with the near end ball at the top of its swing, so the last frame meets the first."
    },
    "seed": {
      "param": "seed",
      "behavior": "Seed changes the wood grain of the base."
    }
  },
  "composition": {
    "inputs": "Time within the loop; the balls' finish and number, how many are lifted, the swing and the cycles per loop.",
    "outputs": "A THREE.Group: base, feet, rails, posts, strings and balls, standing on y = 0.",
    "coordinates": "1 unit = 10 cm. The balls have a radius of 0.5 and touch at rest; the rails stand 6.75 above the base; strings run from rails 1.9 apart to the top of each ball.",
    "lighting": "Physical metals: needs scene.environment for the balls to mirror the room; a shadow-casting key light draws the strings' and balls' shadows on the base.",
    "timing": "update(time, loopSeconds, { cycles }) is a pure function of time; frames render in any order.",
    "compatibleWith": [
      "chrome-material",
      "orbit-camera",
      "kinetic-title"
    ],
    "notes": [
      "Each ball hangs from two strings, so it swings only in the plane of the row; the strings are taut at every angle.",
      "The demo's reflection is a second, upside-down cradle seen through a translucent table."
    ]
  },
  "reuse": [
    "Satisfying loop: Chrome on walnut, camera drift on.",
    "Cause and effect: Gold on black with two lifted, behind a title about chain reactions.",
    "Desk scene: add the group to your own table and call update with your timeline."
  ],
  "integration": {
    "newProject": "Set scene.environment (createStudioEnvironment from Chrome Material works), add createNewtonsCradle().group and a shadow-casting light, and call update(time, loopSeconds, { cycles }) each frame.",
    "existingProject": "Copy src/newtons-cradle.js. Add the group to your scene, scale it, and call update(seconds, loopSeconds) every frame."
  },
  "performance": {
    "notes": "About fifty meshes built once; only the balls and their strings are reposed each frame. Smooth at 1080p on laptop GPUs.",
    "limits": "Software WebGL (no GPU) renders slowly."
  },
  "limitations": [
    "The swing is an idealised cycle (a cosine in the swinging ball, the middle balls perfectly still): no slow loss of energy, no jitter of the middle balls.",
    "Balls do not rotate: they are smooth, untextured spheres."
  ],
  "license": {
    "spdx": "MIT",
    "notice": "Copyright (c) 2026 AI Pixel Wizard. Released under the MIT License. See LICENSE in this folder.",
    "thirdParty": [
      {
        "name": "three.js",
        "version": "0.185.1",
        "license": "MIT",
        "url": "https://github.com/mrdoob/three.js"
      }
    ]
  },
  "provenance": "Adapted from the owner's threejs-sketches/webgpu-newton-cradle (mechanical-kinetic, MIT), rebuilt for AI Pixel Wizard in October 2026: V-strung polished balls on a chrome frame and walnut base, a four-quarter swing that loops exactly, a mirrored table, studio light and shadows, and the frame/time contract.",
  "changelog": [
    {
      "version": "1.0.0",
      "date": "2026-10-05",
      "notes": "Initial release."
    }
  ]
}
