@three.ez/interaction
v0.0.2
Published
Enhance 3D scene interactions with events, drag & drop, and focus management. Simplify three.js development with ease.
Downloads
120
Readme
three.ez - Interaction
Simplify your three.js application development with three.ez!
Enhance 3D scene interactions with events, drag & drop, and focus management. Simplify three.js development with ease.
Example using three.ez/main
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(70).translateZ(1) }); // create the view to be rendered
Example using three.js vanilla
import { BoxGeometry, Mesh, MeshBasicMaterial, PerspectiveCamera, Scene, WebGLRenderer } from 'three';
import { InteractionManager } from '@three.ez/interaction';
const camera = new PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.z = 2;
const scene = new Scene();
const renderer = new WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Add interactionManager to the scene
const interactionManager = new InteractionManager(renderer, scene, camera);
camera.on('viewportresize', (e) => {
camera.aspect = e.width / e.height;
camera.updateProjectionMatrix();
});
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
});
const mesh = new Mesh(new BoxGeometry(), new MeshBasicMaterial({ color: 'white' }));
scene.add(mesh);
mesh.draggable = true;
mesh.on('animate', (e) => {
if (mesh.hovered) return;
mesh.rotation.z += e.delta;
});
renderer.setAnimationLoop((time) => {
// Update interactions
interactionManager.update(time);
renderer.render(scene, camera);
});
This library has two dependency:
three.js r123+
@three.ez/view-manager
🔑 Key Features
✨ Event Programming
Add interactions to Object3D
through programmable events, similar to DOM events
, including a propagation system.
See events list here: Interaction, Miscellaneous, Update.
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'));
🔥 Drag and Drop
Integrate drag and drop functionality. The drag is cancelled by pressing ESC.
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}`));
🚀 Focus and Blur
Enhance interactivity with focus and blur events.
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'));
✂️ Resize Handling
Utilize the viewportResize
event to easily set the resolution for custom shaders.
const line = new Line2(geometry, material);
line.on('viewportresize', (e) => material.resolution.set(e.width, e.height));
⚙️ Raycasting Customisable
Choose between continuous or mouse movement-based raycasting, optimizing intersection operations. Set which objects to intersect from the main raycasting.
const scene = new Scene();
scene.continuousRaycasting = true; // default is false
const box = new Mesh(geometry, material);
box.interceptByRaycaster = false; // default is true
🎯 Hitbox Functionality
Leverage hitboxes for customized intersections or simplified calculations.
const ring = new Mesh(new RingGeometry(1, 1.5), new MeshBasicMaterial());
ring.hitboxes = [new Hitbox(new CircleGeometry(1.5))]; // intercept also inside the ring
⬇️ Installation
You can install it via npm using the following command:
npm install @three.ez/interaction
Or can import it from CDN:
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/[email protected]/build/three.module.js",
"three/examples/jsm": "https://unpkg.com/[email protected]/examples/jsm/",
"@three.ez/view-manager": "https://unpkg.com/@three.ez/[email protected]/bundle.js",
"@three.ez/interaction": "https://unpkg.com/@three.ez/[email protected]/bundle.js"
}
}
</script>
🧑💻 Live Examples
These examples use vite
, and some mobile devices may run out of memory. However, there is one example without it.
Three.js vanilla
Three.ez/main
- Template — Template Extended — Template No Vite
- Smart Rendering
- Events — Click On Scene To Add Box
- Focus — Focus Outline (post-processing)
- Drag & Drop — LOD Draggable — Drag Limits
- Continuous Raycasting
- Hitbox
- Draggable Box OrbitControls
📚 Documentation
The tutorial is available here (work in progress). The API documentation is available here.
🤝 Contributing
Any help is highly appreciated. If you would like to contribute to this package or report problems, feel free to open a bug or pull request.
❔ Questions?
If you have questions or need assistance, you can ask on our discord server.
👀 Future Work
- Evaluate if pointerup event needs rework.
- Raycasting optimization on static scene.
- Raycasting optimization if there are no events on pointer movement.
⭐ Like it?
If you find this project helpful, I would greatly appreciate it if you could leave a star on this repository! This helps me know that you appreciate my work and encourages me to continue improving it. Thank you so much for your support! 🌟