Skip to content

Instantly share code, notes, and snippets.

@ascorbic
Last active March 22, 2023 19:13
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ascorbic/f01009247f859f0d76b8b92d34ae87bd to your computer and use it in GitHub Desktop.
Save ascorbic/f01009247f859f0d76b8b92d34ae87bd to your computer and use it in GitHub Desktop.
Spine/React demo
import React, { useState, useEffect, useCallback } from "react";
import * as PIXI from "pixi.js";
import { Stage } from "@inlet/react-pixi";
import Spine from "./Spine";
window.PIXI = PIXI;
const mixes = [
{
from: "walk",
to: "jump",
duration: 0.2
},
{
from: "jump",
to: "walk",
duration: 0.4
},
{
from: "portal",
to: "walk",
duration: 0.4
}
];
export const App: React.FC = () => {
const [spineData, setSpineData] = useState();
const [animationState, setAnimationState] = useState<
PIXI.spine.core.AnimationState | undefined
>();
useEffect(() => {
const initSpine = async () => {
await import("pixi-spine");
const loader = new PIXI.Loader();
loader
.add("spineboy", "/public/assets/spineboy/spineboy.json")
.load((loader, res) => {
setSpineData(res?.spineboy?.spineData);
});
};
initSpine();
}, []);
const stateRef = useCallback((state: PIXI.spine.core.AnimationState) => {
if (state) {
state.setAnimation(0, "portal", false);
state.addAnimation(0, "walk", true, 0);
}
setAnimationState(state);
}, []);
const jump = useCallback(() => {
if (animationState) {
animationState.setAnimation(0, "jump", false);
animationState.addAnimation(0, "walk", true, 0);
}
}, [animationState]);
return (
<div>
<button onClick={jump}>Jump</button>
<Stage options={{ transparent: true }}>
{spineData && (
<Spine
x={200}
y={590}
spineData={spineData}
scale={0.5}
mixes={mixes}
animationStateCallback={stateRef}
/>
)}
</Stage>
</div>
);
};
import { PixiComponent, applyDefaultProps } from "@inlet/react-pixi";
interface SpineMix {
from: string;
to: string;
duration: number;
}
interface Props {
x?: number;
y?: number;
spineData: PIXI.spine.core.SkeletonData;
scale?: number;
visible?: boolean;
tint?: number;
delayLimit?: number;
mixes?: SpineMix[];
animationStateCallback?: (ref: PIXI.spine.core.AnimationState) => void;
}
export default PixiComponent<Props, PIXI.spine.Spine>("Spine", {
create: ({ spineData }) => {
const spine = new PIXI.spine.Spine(spineData);
return spine;
},
applyProps: (instance, oldProps, newProps) => {
const {
mixes = [],
scale = 1,
animationStateCallback,
...newP
} = newProps;
applyDefaultProps(instance, oldProps, newP);
instance.scale.set(scale);
mixes.forEach(mix =>
instance.stateData.setMix(mix.from, mix.to, mix.duration)
);
if (animationStateCallback) {
animationStateCallback(instance.state);
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment