Making your Three.js experiences interactive is crucial for engaging users. However, simply responding to clicks or mouse movements isn't enough. We need to ensure this interactivity is not only smooth and responsive but also accessible to a wider audience. This section will guide you through best practices for achieving both.
One of the most common ways to interact with 3D objects is by detecting clicks or taps. In Three.js, this is typically achieved using raycasting. A raycaster shoots a ray from a point in the scene (usually the camera's position or the mouse cursor's projected position) and checks for intersections with objects. It's vital to handle these intersections efficiently and provide clear visual feedback to the user.
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
function onMouseMove(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
}
function update() {
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(scene.children);
for (let i = 0; i < intersects.length; i++) {
// Handle intersection with intersects[i].object
}
}
window.addEventListener('mousemove', onMouseMove, false);
// Call update() in your animation loopResponsiveness is key for a good user experience. This means your interactive elements should react quickly to user input without lag. Optimizing your raycasting and intersection checks is paramount. Avoid performing complex calculations for every single frame if possible. Consider debouncing or throttling event listeners for frequent events like mouse movement.
Visual feedback is essential. When a user interacts with an object, they should know it. This can be achieved by highlighting the object, changing its color, scaling it slightly, or displaying tooltips. For more complex interactions, consider subtle animations to indicate state changes. This immediate feedback confirms the user's action has been registered.
const originalColor = object.material.color.getHex();
function onObjectClick(object) {
object.material.color.setHex(0xff0000); // Highlight in red
setTimeout(() => {
object.material.color.setHex(originalColor); // Revert to original color
}, 200);
}