0.0.2 ā€¢ Published 1 month ago

@three.ez/interaction v0.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
1 month ago

three.ez - Interaction

npm Quality Gate Status DeepScan grade Stars BundlePhobia Discord

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/three@0.162.0/build/three.module.js",
    "three/examples/jsm": "https://unpkg.com/three@0.162.0/examples/jsm/",
    "@three.ez/view-manager": "https://unpkg.com/@three.ez/view-manager@0.0.2/bundle.js",
    "@three.ez/interaction": "https://unpkg.com/@three.ez/interaction@0.0.2/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

Examples Collection

šŸ“š 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! šŸŒŸ