{"id":23824541,"url":"https://github.com/jgtools/ttt3d","last_synced_at":"2026-05-17T19:03:20.664Z","repository":{"id":64409117,"uuid":"575155963","full_name":"JGTools/TTT3D","owner":"JGTools","description":"Tiny Transform Transitions 3D","archived":false,"fork":false,"pushed_at":"2023-09-14T12:54:38.000Z","size":138,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-11T19:25:38.701Z","etag":null,"topics":["3d","animation","javascript","jgtools","threejs","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JGTools.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-06T22:02:22.000Z","updated_at":"2024-08-05T16:04:17.000Z","dependencies_parsed_at":"2024-11-28T00:46:22.393Z","dependency_job_id":null,"html_url":"https://github.com/JGTools/TTT3D","commit_stats":{"total_commits":30,"total_committers":3,"mean_commits":10.0,"dds":0.4666666666666667,"last_synced_commit":"f7dad99cc4f17955c1c6675c57226865fb2d1393"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/JGTools/TTT3D","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JGTools%2FTTT3D","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JGTools%2FTTT3D/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JGTools%2FTTT3D/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JGTools%2FTTT3D/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JGTools","download_url":"https://codeload.github.com/JGTools/TTT3D/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JGTools%2FTTT3D/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33151625,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-17T09:28:26.183Z","status":"ssl_error","status_checked_at":"2026-05-17T09:27:52.702Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3d","animation","javascript","jgtools","threejs","typescript"],"created_at":"2025-01-02T11:12:23.385Z","updated_at":"2026-05-17T19:03:20.626Z","avatar_url":"https://github.com/JGTools.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TTT3D\n\n[![npm](https://img.shields.io/npm/v/@jgtools/ttt3d)](https://www.npmjs.com/package/@jgtools/ttt3d)\n[![npm](https://img.shields.io/npm/dm/@jgtools/ttt3d)](https://www.npmjs.com/package/@jgtools/ttt3d)\n[![GitHub](https://img.shields.io/github/license/jgtools/ttt3d)](https://github.com/git/git-scm.com/blob/main/MIT-LICENSE.txt)\n\nTiny Transform Transitions 3D\n\n## Features\n\n- :heavy_check_mark: Animate 3D objects using lambda functions\n- :heavy_check_mark: Can be used with any 3D library\n- :blue_square: Written in TypeScript\n\n## Installation\n\n### Using npm\n\n```bash\nnpm i @jgtools/ttt3d\n```\n\n```javascript\nimport TTT3D from \"@jgtools/ttt3d\";\n// ...\n```\n\n### Using cdn\n\n```html\n\u003cscript type=\"module\"\u003e\n    import TTT3D from \"https://cdn.jsdelivr.net/npm/@jgtools/ttt3d@1.1.0/dist/index.min.js\";\n    // ...\n\u003c/script\u003e\n```\n\n## Usage\n\n### Simple example\n\nAnimating a jumping cube.\n\n- Full code [here](examples/simple/index.html)\n- Codepen demo [here](https://codepen.io/erik1001/pen/wvxvKwo)\n\nCreate cube and define animations:\n\n```javascript\nconst geo = new THREE.BoxGeometry(1, 1, 1);\nconst mat = new THREE.MeshLambertMaterial({ color: 0x00ffff });\nconst cube = new THREE.Mesh(geo, mat);\nscene.add(cube);\n\n// create ttt3d instance\n// [pos.x, pos.y, pos.z, rot.x, rot.y, rot.z, scale.x, scale.y, scale.z]\nconst origins = {\n  cube: [0, 0, 0, 0, 0, 0, 1, 1, 1],\n};\nconst ttt = new TTT3D(origins);\n\n// setup jump transition\nttt.add(\"jump\", (c) =\u003e {\n  const t = Math.sin(c * Math.PI);\n  return {\n    cube: [0, t * 2, 0, 0, t * 4, 0, 0, t, 0],\n  };\n});\n\n// play jump transition every 3 seconds\nsetInterval(() =\u003e ttt.play(\"jump\"), 3000);\n```\n\nUpdate each frame and apply result to mesh:\n\n```javascript\n// update transition system\nconst res = ttt.update(delta);\n\n// update mesh transform\nconst part = res[\"cube\"];\ncube.position.set(part[0], part[1], part[2]);\ncube.rotation.set(part[3], part[4], part[5]);\ncube.scale.set(part[6], part[7], part[8]);\n```\n\n### Advanced example\n\nAnimating an idling, walking and jumping cube with legs.\n\n- Full code [here](examples/advanced)\n- Codepen demo [here](https://codepen.io/erik1001/pen/jOpOwPL)\n\nCreate player parts and define animations:\n\n```javascript\nconst player = new THREE.Group();\nscene.add(player);\n\nconst matHead = new THREE.MeshLambertMaterial({ color: 0x00ff00 });\nconst matFoot = new THREE.MeshLambertMaterial({ color: 0xff0000 });\nconst geo = new THREE.BoxGeometry();\n\nconst head = new THREE.Mesh(geo, matHead);\nconst rightFoot = new THREE.Mesh(geo, matFoot);\nconst leftFoot = new THREE.Mesh(geo, matFoot);\nplayer.add(head);\nplayer.add(rightFoot);\nplayer.add(leftFoot);\n\nconst playerParts = new Map();\nplayerParts.set(\"head\", head);\nplayerParts.set(\"rightFoot\", rightFoot);\nplayerParts.set(\"leftFoot\", leftFoot);\n\n// setup ttt3d with default transforms\nconst origins = {\n  head: [0, 0.8, 0, 0, 0, 0, 1, 1, 1],\n  rightFoot: [-0.3, -0.5, 0, 0, 0, 0, 0.4, 0.3, 0.6],\n  leftFoot: [0.3, -0.5, 0, 0, 0, 0, 0.4, 0.3, 0.6],\n};\nconst ttt = new TTT3D(origins);\n\n// create animations\nttt.add(\"idle\", (c) =\u003e {\n  const t = Math.sin(c * Math.PI);\n  return {\n    head: [0, t * 0.1],\n  };\n});\nttt.add(\"walk\", (c) =\u003e {\n  const t = Math.sin(c * Math.PI * 2);\n  return {\n    head: [0, 0, 0.2 * t],\n    rightFoot: [0, 0, t * 0.3, -0.2 * t],\n    leftFoot: [0, 0, -t * 0.3, 0.2 * t],\n  };\n});\nttt.add(\"jump\", (c) =\u003e {\n  const t = Math.sin(c * Math.PI);\n  const hs = outElastic(t);\n  return {\n    head: [0, t, 0, -t * 0.4, 0, 0, -hs * 0.4, hs * 0.5, -hs * 0.4],\n    rightFoot: [0, t, 0, t],\n    leftFoot: [0, t * 1.3, 0, t * 1.5],\n  };\n});\n\nttt.play(\"idle\", 1, true);\nttt.play(\"walk\", 0.6, true);\nsetInterval(() =\u003e ttt.play(\"jump\", 0.6), 3000);\n\nlet isWalking = true;\nsetInterval(() =\u003e isWalking = !isWalking, 5000);\n```\n\nUpdate each frame and apply result to meshes:\n\n```javascript\n// blend smoothly between the walk and idle\nconst BLEND_SPEED = 3;\nlet w = ttt.getWeight(\"idle\") || 0;\nw += delta * (isWalking ? -BLEND_SPEED : BLEND_SPEED);\nw = Math.min(Math.max(0, w), 1);\nttt.setWeight(\"idle\", w);\nttt.setWeight(\"walk\", 1 - w);\n\n// update ttt and apply transforms to meshes\nconst res = ttt.update(delta);\nfor (const [k, e] of playerParts) {\n  e.position.set(res[k][0], res[k][1], res[k][2]);\n  e.rotation.set(res[k][3], res[k][4], res[k][5]);\n  e.scale.set(res[k][6], res[k][7], res[k][8]);\n}\n```\n\n## Docs\n#### `new TTT3D(origins: { [key: string]: number[] })`\nCreate a new TTT3D instance.\n\n#### `add(name: string, fn: (c: number) =\u003e number[]): void`\nAdd a new animation.\n\n#### `play(name: string, speed: number = 1, loop: boolean = false): void`\nPlay an animation.\n\n#### `stop(name: string): void`\nStop an animation.\n\n#### `update(delta: number): { [key: string]: number[] }`\nUpdate the transition system and return the result. \n\n#### `setWeight(name: string, weight: number): void`\nSet the weight of an animation.\n\n#### `setRate(name: string, rate: number): void`\nSet the rate of an animation.\n\n#### `setLoop(name: string, loop: boolean): void`\nSet whether an animation loops.\n\n#### `setCounter(name: string, counter: number): void`\nSet the counter value of an animation.\n\n#### `getWeight(name: string): number`\nGet the weight of an animation.\n\n#### `getRate(name: string): number`\nGet the rate of an animation.\n\n#### `getLoop(name: string): boolean`\nGet whether an animation loops.\n\n#### `getCounter(name: string): number`\nGet the counter value of an animation.\n\n## Build Instructions\n\n```sh\nnpm i\nnpm run build\n```\n\n## License\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjgtools%2Fttt3d","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjgtools%2Fttt3d","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjgtools%2Fttt3d/lists"}