Simplify three.js development, including events, drag & drop, binding, focus management, smart rendering, tweening and more.
npm install @three.ez/main
Simplify your three.js application development with three.ez!
InstancedMesh with features for performance and usability
BatchedMesh extension methods and enhancements for better performance and usability
three.js applications, extends the functionalities of Object3D and Scene classes, making their usage more straightforward, and introduce utility classes.
typescript
import { Scene, Mesh, BoxGeometry, MeshNormalMaterial } from 'three';
import { Main, PerspectiveCameraAuto } from '@three.ez/main';
const box = new Mesh(new BoxGeometry(), new MeshNormalMaterial());
box.draggable = true; // make it draggable
box.on('animate', (e) => box.rotateX(e.delta).rotateY(e.delta * 2)); // animate it every frame
box.on(['pointerover', 'pointerout'], (e) => box.scale.setScalar(e.type === 'pointerover' ? 1.5 : 1));
const scene = new Scene().add(box);
const main = new Main(); // init inside the renderer, and handle events, resize, etc
main.createView({ scene, camera: new PerspectiveCameraAuto().translateZ(10) }); // create the view to be rendered
`
Related libraries
š§āš» Live examples
These examples use vite, and some mobile devices may run out of memory.
Examples Collection
- Template
ā Template Extended
ā Template No Vite
- Smart Rendering
- Multiple Views
ā Multiple Views Wireframe
ā Multiple Views Switch
- Asset Management
- Binding
ā Binding Collisions
- Events
ā Click On Scene To Add Box
- Focus
ā Focus Outline (post-processing)
- Drag & Drop
ā LOD Draggable
ā Drag Limits
- Continuous Raycasting
- Hitbox
- Tweening
ā Tweening Custom Progress
- InstancedMeshEntity
ā InstancedMeshEntity Performance
- Draggable Box OrbitControls
- Textbox (troika-three-text)
- Bubble Refraction
š Documentation
The tutorial is available here (work in progress).
The API documentation is available here.
ā¬ļø Installation
You can install it via npm using the following command:
`bash
npm install @three.ez/main
`
Or can import it from CDN:
`html
`
ā Questions?
Need help? Join us on Discord or open an issue on GitHub.
ā Like it?
If you like this project, please leave a star. Thank you! ā¤ļø
š Features
$3
Add interactions to Object3D through programmable events, similar to DOM events, including a propagation system.
See events list here: Interaction, Miscellaneous, Update.
`typescript
const box = new Mesh(geometry, material);
box.on('click', (e) => e.stopPropagation());
box.on('animate', (e) => console.log('animate'));
box.on('positionchange', () => console.log('position changed'));
`
$3
Integrate drag and drop functionality. The drag is cancelled by pressing ESC.
`typescript
const box = new Mesh(geometry, material);
box.draggable = true;
box.findDropTarget = true;
box.on('drag', (e) => console.log(new position: ${e.position}));
const plane = new Mesh(geometry, material);
plane.on('drop', (e) => console.log(obj dropped on this: ${e.relatedTarget}));
`
$3
Enhance interactivity with focus and blur events.
`typescript
const box = new Mesh(geometry, material);
box.focusable = true; // default is true
box.on('focus', (e) => console.log('focused'));
box.on('blur', (e) => console.log('focus lost'));
`
$3
Streamline the management of Object3D properties.
`typescript
const box = new Mesh(geometry, material);
box.bindProperty('visible', () => box.parent?.enabled);
`
$3
Automatically resizes the Renderer, Camera, and EffectComposer.
Utilize the viewportResize event to easily set the resolution for custom shaders.
`typescript
const line = new Line2(geometry, material);
line.on('viewportresize', (e) => material.resolution.set(e.width, e.height));
`
$3
Optimize performance by rendering frames only when necessary, reducing computational overhead.
Automatically identifies changes in position, scale, rotation, visibility, focus, blurring and addition or removal of objects.
`typescript
const scene = new Scene();
scene.activeSmartRendering();
const box = new Mesh(new BoxGeometry(), new MeshLambertMaterial({ color: 'green' }));
box.draggable = true; // if you drag the frame, it automatically detects changes and renders the frame
box.material.color.set('yellow');
box.needsRender = true; // necessary because color change cannot be automatically detected
`
$3
Effortlessly manage rendering for multiple scenes or viewports within a single canvas.
`typescript
const main = new Main();
main.createView({ scene, camera, viewport: { left: 0, bottom: 0, width: 0.5, height: 1 } });
main.createView({ scene, camera, viewport: { left: 0.5, bottom: 0, width: 0.5, height: 1 } });
`
$3
Efficiently load and preload the assets for your 3D projects.
load:
`typescript
const audioBuffer = await Asset.load(AudioLoader, 'audio.mp3', onProgressCallback, onErrorCallback);
`
preload:
`typescript
// soldier.js
Asset.preload(GLTFLoader, 'https://threejs.org/examples/models/gltf/Soldier.glb');
export class Soldier extends Group {
constructor() {
super();
const gltf = Asset.get('https://threejs.org/examples/models/gltf/Soldier.glb');
this.add(...gltf.scene.children);
}
}
// main.js
await Asset.preloadAllPending({ onProgress: (e) => console.log(e * 100 + '%'), onError: (e) => console.error(e) });
const main = new Main();
const soldier = new Soldier();
`
$3
Create smooth animations effortlessly with built-in tweening.
`typescript
box.tween().by(1000, { position: new Vector3(0, 0.5, 0) }, { easing: 'easeInOutBack' }).yoyoForever().start();
new Tween(box)
.by(2000, { scale: 1, rotation: new Euler(Math.PI * 2, Math.PI, 0) }, { easing: 'easeOutElastic' })
.delay(200)
.to(1000, { scale: 1 }, { easing: 'easeOutBounce' })
.start();
`
$3
Choose between continuous or mouse movement-based raycasting, optimizing intersection operations.
Set which objects to intersect from the main raycasting.
`typescript
const scene = new Scene();
scene.continuousRaycasting = true; // default is false
const box = new Mesh(geometry, material);
box.interceptByRaycaster = false; // default is true
`
$3
Leverage hitboxes for customized intersections or simplified calculations.
`typescript
const ring = new Mesh(new RingGeometry(1, 1.5), new MeshBasicMaterial());
ring.hitboxes = [new Hitbox(new CircleGeometry(1.5))]; // intercept also inside the ring
`
$3
Find and select Object3D using powerful query selectors.
`typescript
scene.querySelectorAll('Mesh'); // Selects all the meshes in the scene.
scene.querySelectorAll('[name=box]'); // Selects all Object3D that have 'box' as their name.
scene.querySelectorAll('[name*=box]'); // Selects all Object3D that have 'box' anywhere in their name.
scene.querySelectorAll('Mesh.even'); // Selects meshes with both 'Mesh' type and 'even' tag.
scene.querySelectorAll('Group .even'); // Selects all Object3D with 'even' tag that are children of a 'Group'.
scene.querySelectorAll('Group > .even'); // Selects all direct children with 'even' tag under a 'Group'.
scene.querySelectorAll('Mesh, SkinnedMesh'); // Selects all meshes and skinned meshes in the scene.
``