Project Plateau
Project Plateau: four glass plates, one living valley, and the road back to camp.
spine-layout is a composition framework for game UIs, layouts and animations built on top of Pixi.js. It combines three layers:
GamesTypeScript · JavaScriptGitHub @pixijs-userlandOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
A spine composition framework built on Pixi.js. It lets you assemble flexible scenes with Spine skeletons, and provides a powerful animation system with minimal code.
Loading the full README.
Read the full README ↗A spine composition framework built on Pixi.js. It lets you assemble flexible scenes with Spine skeletons, and provides a powerful animation system with minimal code.
Full documentation: userland.pixijs.io/spine-layout
SpineLayout is a Pixi.js Container that acts as a facade over seven specialized controllers:
SpineLayout (Container)
├── AnimationsController — playback, states, events, track management
├── SkinsController — skin switching across spines
├── SpineController — bone/slot queries, global positions, cloning
├── TextsController — dynamic text rendering & number animation
├── SceneController — hierarchical composition (nest spines, attach texts/buttons)
├── PointerController — bones that follow the mouse or finger
└── OrientationController — poses the layout for the shape of the screen
All spines are stored in a central Map<SpineID, Spine> registry and each controller operates against that registry.
The core renders through an Engine, so one scene runs on every Pixi from 4 to 8. A game picks its
Pixi when it creates the engine; the Spine runtime is then picked from the export version, among
the runtimes registered for that Pixi. The exports of one layout must all be of one Spine version:
a layout that mixes them throws MixedSpineVersionsError and builds nothing.
| Entry | Pixi | Spine runtimes |
|---|---|---|
@pixijs-userland/spine-layout | pixi.js v8 | spine-pixi-v8 4.3 (unchanged default entry) |
@pixijs-userland/spine-layout/pixi8 | pixi.js v8 | spine-pixi-v8 4.2 and 4.3 |
@pixijs-userland/spine-layout/pixi7 | Pixi 7 (window.PIXI) | @pixi-spine/* 4.0 (3.7, 3.8, 4.1; 4.0 through 4.1), spine-pixi-v7 4.2 and 4.3 |
@pixijs-userland/spine-layout/pixi6 | Pixi 6 (window.PIXI) | @pixi-spine/* 3.1 (3.7, 3.8, 4.0, 4.1) |
@pixijs-userland/spine-layout/pixi5 | Pixi 5 (window.PIXI) | pixi-spine 2.1 (3.8) or 2.0 (3.7), one per page |
@pixijs-userland/spine-layout/pixi4 | PIXI v4.8.9 (window.PIXI) | pixi-spine 1.6 (3.8) or 1.5 (3.7), one per page |
@pixijs-userland/spine-layout/core | none | SpineLayoutCore, the runtime matrix, choosePixi, pickRuntime |
@pixijs-userland/spine-layout/runtimes binds runtime packages to an engine and discovers the ones
a page loaded as globals. A Spine export is read by the runtime of its own editor major.minor; a
project pin can name another, and 4.0 and 4.1 exports reach the next runtime through a JSON
pre-pass. On Pixi 4–7 the stack is loaded as <script> tags and the engine is handed
window.PIXI:
import { createPixi4Engine, SpineLayoutCore } from '@pixijs-userland/spine-layout/pixi4';
const engine = createPixi4Engine(PIXI, { renderer: app.renderer });
const layout = new SpineLayoutCore({ engine });
A game whose own loader already reads its skeletons (unicore reads binary Spine 3.8 into
SkeletonData with its atlas) hands them over as they are: engine.assets.set('spine/bg.json', skeletonData). The engine takes a SkeletonData under a skeleton alias as read, with no atlas.
A project is one Spine version; skeletonVersion(skeleton) reads it from a .json or .skel.
One Pixi major is live per page. See the Engines guide
for loading, the differences between the engines and how to write another.
examples/ has one scene per Pixi major, each built with that major's engine from the exports in
examples/assets/: Pixi 8 with spine-pixi-v8 4.3 and a lazily loaded 4.2 in one scene, Pixi 7
with a Spine 3.8 and a 4.3 layout on one engine, and Pixi 6, 5 and 4 each on their own pixi-spine
with the 3.8 layout (texts, a bitmap font, a button, a second skin and particles). From this
package, after pnpm install:
pnpm examples --port <port> --strictPort --no-open
Then open http://localhost:<port>/examples/. Vite serves the layout from src; the legacy
stacks load as <script> globals, and the runtimes with no browser script of their own
(@pixi-spine/*, spine-pixi-v7) are bundled into examples/vendor/ as the server starts.
const layout = new SpineLayout({ debug: true });
await layout.createInstancesFromManifest(manifest, 'spines');
createInstancesFromManifest parses the manifest for .atlas / .json / .png triplets, builds the scene from its root, then wires the full hierarchy.
The scene has one entry point — root, or whatever options.root names. It is built first, its
spine_<id> slots name the spines built next, theirs name the ones after that, and so on down the
tree; the layout container holds the root and nothing else. A skeleton that is loaded but embedded
nowhere is not instanced at all — nothing points at it, so nothing would place it. createInstance
builds one anyway, together with everything it embeds in turn.
This is the beginning of the README. Read the rest at the original. Read the full README ↗