triaxis
v1.0.0
Published
TriAxis is a JavaScript/TypeScript library designed to make integrating 3D animations and visualizations into web and mobile applications extremely simple and fast. It serves as a lightweight abstraction layer on top of the Three.js engine to hide the com
Readme
TriAxis
TriAxis is a JavaScript/TypeScript library that makes 3D scenes and animations dead-simple for the Web (and soon, Mobile). It wraps Three.js with a friendly, fluent API so developers can initialize a scene, add objects, and animate them in just a few lines — without handling raw Three.js Scene/Camera/Renderer for common cases.
Installation
npm install triaxis
# or
yarn add triaxisQuick Start
import { TriAxis } from 'triaxis';
// HTML: <canvas id="canvas"></canvas>
const scene = TriAxis.init('#canvas', { background: '#101820' });
const cube = scene
.addCube({ color: '#2E7', size: 2, position: [0, 1, 0] })
.on('click', () => console.log('Cube clicked'));
cube.animateTo({ y: 3, duration: 1200 });Core Concepts
TriAxis.init(target, options)initializes scene, camera, lights, controls and starts the render loop.ObjectHandleis returned for any created object and exposes fluent transform and animation methods.- Easing, timelines, scroll-driven animations and camera utilities are built-in.
API Overview
Initialization
const scene = TriAxis.init('#canvas', {
background: '#000',
antialias: true,
camera: { fov: 60, position: [0, 2, 5] },
lights: {
ambient: { intensity: 0.6 },
directional: { intensity: 0.8, position: [3, 5, 2] }
},
controls: { enable: true }
});Primitives & Images
const cube = scene.addCube({ color: '#00aaff', size: 1, position: [0, 0, 0] });
const sphere = scene.addSphere({ color: '#ffaa00', size: 1.5 });
const plane = scene.addPlane({ color: '#ccc', width: 2, height: 2 });
// Add an image as textured plane
const img = await scene.addImage('/assets/hero.png', { size: 3, position: [0, 0, -1] });ObjectHandle Methods
cube.setPosition(1, 0.5, 0).setScale(1.2).rotateY(Math.PI / 4);
// Basic tweens
cube.moveTo({ x: 2, duration: 800 });
cube.rotateTo({ rotY: Math.PI, duration: 1000 });
cube.scaleTo(1.5, 600);
cube.fadeTo(0.5, 500);
cube.colorTo('#FF0066', 400);
cube.oscillate('y', 0.3, 1.5, 2000);
// Advanced
cube.springTo({ to: { y: 1.2 }, stiffness: 160, damping: 20, durationMax: 1200 });
cube.orbitAround([0, 0, 0], { radius: 3, speed: 0.4, axis: 'y', duration: 4000 });
cube.followBezier(
[[0, 0, 0], [2, 1, 0], [1, 2, 1], [0, 0, 2]],
3000,
TriAxis.easing.sineInOut
);
img.spriteSheet({ cols: 4, rows: 4, fps: 12, duration: 2000 });Camera Animations
scene.zoomTo(50, 600, TriAxis.easing.sineInOut);
scene.dollyTo([0, 3, 8], 800, TriAxis.easing.cubicOut);
scene.lookAtTo([0, 0, 0], 800, TriAxis.easing.quadInOut);
scene.cameraOrbitAround(cube.getObject?.('cube-1')?.obj ?? cube as any, { duration: 3000 });Easing
import { TriAxis } from 'triaxis';
// Available: linear, quad/cubic/quart/quint, sine, expo, circ, back, elastic, bounce
const ease = TriAxis.easing.cubicInOut;
cube.animateTo({ y: 2, duration: 1000, easing: ease });Timelines
import { Timeline } from 'triaxis';
const tl = new Timeline()
.to(cube, { y: 2, duration: 800, easing: TriAxis.easing.quadOut })
.wait(200)
.parallel([
{ handle: cube, props: { color: '#FF0066', duration: 400 } },
{ handle: cube, props: { scale: 1.3, duration: 400 } }
])
.play();Animation Presets
// Use TriAxis animations namespace to keep package identity
await TriAxis.animations.pulse(cube, 1.25, 600, { easingIn: TriAxis.easing.elasticOut });
await TriAxis.animations.shake(cube, 0.2, 4, 500);
await TriAxis.animations.float(cube, 0.3, 2000, { axis: 'y' });
await TriAxis.animations.hover(cube, 0.5, 1500);
await TriAxis.animations.bounce(cube, 1, 800, { easingDown: TriAxis.easing.bounceOut });
await TriAxis.animations.spin(cube, 1, 1000, { axis: 'y' });
await TriAxis.animations.fadeIn(img, 600);
await TriAxis.animations.colorFlash(cube, '#FFEE00', 400, { backColor: '#ffffff' });
await TriAxis.animations.popIn(cube, 500);
await TriAxis.animations.popOut(cube, 500);Scroll Animations
const scroll = TriAxis.scroll.animator(window, { smoothing: 0.25 });
const hero = await scene.addImage('/hero.png', { size: 3 });
TriAxis.scroll.reveal(scroll, hero, 1, [0.05, 0.15], TriAxis.easing.sineInOut);
TriAxis.scroll.parallax(scroll, hero, 'y', 2, [0.15, 0.9]);
TriAxis.scroll.cameraRail(scene, scroll, [[0, 2, 8], [2, 3, 6], [0, 4, 4]], [0.2, 0.8], TriAxis.easing.quadInOut);
TriAxis.scroll.cameraSections(scene, scroll, [
{ range: [0.0, 0.3], dolly: [0, 2, 8], zoom: 60 },
{ range: [0.3, 0.6], dolly: [2, 3, 6], zoom: 50 },
{ range: [0.6, 1.0], dolly: [0, 4, 4], zoom: 45 }
]);Customization & Callbacks
// Global defaults
TriAxis.configure({ tween: { duration: 800, easing: TriAxis.easing.sineInOut } });
// Per tween
cube.animateTo({
x: 2,
duration: 1200,
delay: 200,
repeat: 1,
yoyo: true,
easing: TriAxis.easing.backOut,
onStart() { /* ... */ },
onUpdate(progress) { /* ... */ },
onComplete() { /* ... */ }
});
// Pause/Cancel
scene.pauseAnimations();
scene.resumeAnimations();
cube.cancelAnimations();GLTF/GLB Models
const car = await scene.loadModel('/models/car.glb');
await car.colorTo('#333333', 300);
await car.moveTo({ z: -2, duration: 800, easing: TriAxis.easing.quadOut });Notes
- Web entry is available now. Mobile (React Native via React Three Fiber) is planned.
- TriAxis runs a single internal render loop; animations are lightweight and composable.
- Avoid recreating materials; TriAxis tweens color/opacity directly where possible.
License
MIT
