Make your 3D project interactive

101 阅读1分钟

🥁 Preface

There are many posts introduced how to make 3D project on a web page by using three.js, but it's not enough. For a qualified developer, make your project interactive is necessary.

👁️Preview

20230310_143811.gif

This is my recent work: make a 2D knowledge graph to 3D, every node in this graph can be clicked and if the node has been clicked , it should show in the center of the view.

😶‍🌫️ Converting 2D position to 3D position

The scene is 3D, click on the screen can only get a 2D position.

container.addEventListener('dblclick',(event)=>{
    const mouseX =  event.clientX;
    const mouseY =  event.clientY;
})

so we need to find a method to figure out the deepth.

In three.js, the idea is emit a half-line from camera to the position where you clicked.

raycaster.svg

then, we can get all the objects that intersect with the half-line.

const raycaster = new Three.Raycaster();
raycaster.setFromCamera({x,y},camera);
const intersectObjects = raycaster.intersectObjects(scene,false)

and the first object in intersectObjects is the object you clicked.

//omit previous code
if(intersectObjects.length>0){
    const clickedObject =  intersectObjects[0].object
}

🥶Two details you need to know

First, the {x,y} paramaters in setFromCamera is not {event.clientX, event.clientY},we need to conver {event.clinetX, event.clientY} to {x, y}.

const rect =  container.getBoundingClientRect();
const x = ((mouseX - rect.left) /  container.clientWidth) * 2 -1;
const y = -((mouseY - rect.top) / container.clientHeight) * 2 + 1;

Second, you can pass an array which contains all the clickable objects to raycaster.intersectObjects() .This make sure you only interact with the object you want.

const clickableObjects = [];
scene.traverse((obj)=>{
    if(obj.clickable){
        clickableObjects.push(obj)
    }
}
const intersectObjects = raycaster.interscetObjects(clickableObjects,false)

🎊Make some animation

We have two way to make object move, one is change the position of the object ,another is change the position of the camera, the result is same.

I choosed change camera position in my project.

GSAP is the most robust high-performance JavaScript animation library

import { gsap } from 'gsap';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
const panning = (controls,selectedObject)=>{
    gasp.to(controls.target,{
        x:selectObject.position.x,
        y:selectObject.position.y,
        z:selectObject.position.z,
        duaration:3,
        ease:'none'
    }
}

By pass controls.target to gasp.to(), gasp will calculate interpolation between controls.target.x to selectObject.position.x , the same as x,y. and in every frame the brower rendered , gasp will auto change control.target's value.

👹The end

This post is a brief introduction about how to make object interactive, in short,if we want to interact with an object, select the object ,then make some change to the object.