Custom Animation
iCraft Player React has a built-in TWEEN library that allows you to create fully custom animation effects directly.
How to Use
After obtaining a player instance through ref
or onReady
, use getElementsByName
or click events to get elements, then directly apply TWEEN animations to element properties (position, rotation, scale, color, etc.).
"use client";
import { ICraftPlayer, ICraftPlayerInstance, TWEEN } from "@icraft/player-react";
import { useRef, useState } from "react";
export default () => {
const [isPaused, setIsPaused] = useState<boolean>(false);
const playerRef = useRef<ICraftPlayerInstance>();
const tweenRef = useRef<TWEEN.Tween<any> | null>(null);
const allAnimationsRef = useRef<TWEEN.Tween<any>[]>([]);
const onReady = (player: ICraftPlayerInstance) => {
playerRef.current = player;
const car = player.getElementsByName("car")?.[0];
if (car) {
startSquarePathAnimation(car);
} else {
}
};
const startSquarePathAnimation = (car: any) => {
const startPos = {
x: car.position.x,
y: car.position.y,
z: car.position.z,
};
const startRot = car.rotation.y;
const pathSegments = [
{
to: { x: startPos.x, y: startPos.y, z: startPos.z + 20 },
rotation: startRot,
},
{
to: { x: startPos.x + 20, y: startPos.y, z: startPos.z + 20 },
rotation: startRot - Math.PI / 2,
},
{
to: { x: startPos.x + 20, y: startPos.y, z: startPos.z },
rotation: startRot - Math.PI,
},
{
to: { x: startPos.x, y: startPos.y, z: startPos.z },
rotation: startRot - (Math.PI * 3) / 2,
},
];
const animations: TWEEN.Tween<any>[] = [];
pathSegments.forEach((segment, index) => {
const moveTween = new TWEEN.Tween(car.position)
.to(segment.to, 2000)
.easing(TWEEN.Easing.Quadratic.InOut);
const rotateTween = new TWEEN.Tween(car.rotation)
.to({ y: segment.rotation }, 300)
.easing(TWEEN.Easing.Quadratic.InOut);
moveTween.onStart(() => {
rotateTween.start();
});
animations.push(moveTween);
});
for (let i = 0; i < animations.length; i++) {
const nextIndex = (i + 1) % animations.length;
animations[i].chain(animations[nextIndex]);
}
allAnimationsRef.current = animations;
animations[0].start();
tweenRef.current = animations[0];
};
const togglePause = () => {
if (isPaused) {
allAnimationsRef.current.forEach((animation) => {
if (animation.isPaused && animation.isPaused()) {
animation.resume();
}
});
setIsPaused(false);
} else {
allAnimationsRef.current.forEach((animation) => {
if (animation.pause) {
animation.pause();
}
});
setIsPaused(true);
}
};
return (
<div style={style}>
<ICraftPlayer
src='/templates/tween.iplayer'
onReady={onReady}
ref={playerRef}
/>
<div style={infoStyle}>
<div style={{ display: "flex", gap: "10px", marginTop: "10px" }}>
<button onClick={togglePause}>{isPaused ? "play" : "pause"}</button>
</div>
</div>
</div>
);
};
const style = {
width: "100%",
height: "100%",
position: "relative" as const,
overflow: "hidden" as const,
};
const infoStyle = {
position: "absolute" as const,
bottom: 10,
right: 10,
padding: "10px",
};
Common Animation Examples
Position Animation
// Move to target position
const moveTween = new TWEEN.Tween(element.position)
.to({ x: 10, y: 5, z: 0 }, 1000)
.easing(TWEEN.Easing.Quadratic.InOut)
.start();
Rotation Animation
// Rotate 360 degrees around Y axis
const rotateTween = new TWEEN.Tween(element.rotation)
.to({ y: element.rotation.y + Math.PI * 2 }, 2000)
.easing(TWEEN.Easing.Cubic.InOut)
.start();
Scale Animation
// Scale to 1.5x
const scaleTween = new TWEEN.Tween(element.scale)
.to({ x: 1.5, y: 1.5, z: 1.5 }, 1000)
.easing(TWEEN.Easing.Back.Out)
.start();
Parallel Animation
// Execute multiple animations simultaneously
const moveTween = new TWEEN.Tween(element.position).to({ x: 5, y: 3, z: 2 }, 2000);
const rotateTween = new TWEEN.Tween(element.rotation).to({ y: Math.PI }, 2000);
const scaleTween = new TWEEN.Tween(element.scale).to({ x: 1.2, y: 1.2, z: 1.2 }, 2000);
// Start simultaneously
moveTween.start();
rotateTween.start();
scaleTween.start();
Chain Animation
// Execute animations sequentially
const firstTween = new TWEEN.Tween(element.position).to({ x: 5 }, 1000);
const secondTween = new TWEEN.Tween(element.position).to({ y: 5 }, 1000);
const thirdTween = new TWEEN.Tween(element.position).to({ z: 5 }, 1000);
// Chain animations
firstTween.chain(secondTween);
secondTween.chain(thirdTween);
firstTween.start();
API
TWEEN
The TWEEN library provides powerful animation capabilities:
Method | Description | Parameters |
---|---|---|
constructor | Create new tween instance | (object: Object) |
to | Set target values | (properties: Object, duration: number) |
easing | Set easing function | (easing: Function) |
start | Start animation | () => Tween |
stop | Stop animation | () => Tween |
chain | Chain next animation | (...tweens: Tween[]) |
yoyo | Enable yoyo effect | (yoyo: boolean) |
repeat | Set repeat count | (times: number) |
onUpdate | Animation update callback | (callback: Function) |
onComplete | Animation complete callback | (callback: Function) |
Easing Functions
TWEEN provides rich easing functions:
TWEEN.Easing.Linear.None
- LinearTWEEN.Easing.Quadratic.In/Out/InOut
- QuadraticTWEEN.Easing.Cubic.In/Out/InOut
- CubicTWEEN.Easing.Quartic.In/Out/InOut
- QuarticTWEEN.Easing.Quintic.In/Out/InOut
- QuinticTWEEN.Easing.Sinusoidal.In/Out/InOut
- SinusoidalTWEEN.Easing.Exponential.In/Out/InOut
- ExponentialTWEEN.Easing.Circular.In/Out/InOut
- CircularTWEEN.Easing.Elastic.In/Out/InOut
- ElasticTWEEN.Easing.Back.In/Out/InOut
- BackTWEEN.Easing.Bounce.In/Out/InOut
- Bounce
Element Properties
Common animatable element properties:
Property | Description | Type |
---|---|---|
position | Position (x, y, z) | Vector3 |
rotation | Rotation (x, y, z) | Euler |
scale | Scale (x, y, z) | Vector3 |
Best Practices
- Performance: Avoid running too many animations simultaneously, use
stop()
method to clean up animations properly - Memory Management: Use refs to save animation instances for easy management and cleanup
- User Experience: Provide ways to stop animations, such as clicking empty space to stop
- Animation Composition: Use chain and parallel animations wisely to create complex effects
- Easing Functions: Choose appropriate easing functions to make animations more natural