먼저 사용하는 함수는 다음과 같습니다. (에니메이션을 위하 GSAP 라이브러리를 사용하였음)
_zoomFit(object3D, viewMode, bFront, viewAngle) { const box = new THREE.Box3().setFromObject(object3D); const sizeBox = box.getSize(new THREE.Vector3()).length(); const centerBox = box.getCenter(new THREE.Vector3()); const offset = new THREE.Vector3(viewMode==="X"?1:0, viewMode==="Y"?1:0, viewMode==="Z"?1:0); if(!bFront) offset.negate(); offset.applyAxisAngle(new THREE.Vector3(1,0,0), THREE.Math.degToRad(viewAngle)); const newPosition = new THREE.Vector3().copy(centerBox).add(offset); const halfSizeModel = sizeBox * 0.5; const halfFov = THREE.Math.degToRad(this._camera.fov * .5); const distance = halfSizeModel / Math.tan(halfFov); const direction = (new THREE.Vector3()).subVectors(newPosition, centerBox).normalize(); newPosition.copy(direction.multiplyScalar(distance).add(centerBox)); const oldPosition = this._camera.position.clone(); gsap.to(this._camera.position, { duration: 0.5, x: newPosition.x, y: newPosition.y, z: newPosition.z}); // camera.lookAt(centerBox.x, centerBox.y, centerBox.z); // OrbitControls를 사용하지 않은 경우 // this._controls.target.copy(centerBox); // OrbitControls를 사용하고 있는 경우 gsap.to(this._controls.target, { duration: 0.5, x: centerBox.x, y: centerBox.y, z: centerBox.z}); }
사용은 줌인 대상을 마우스로 클릭해 선택한다고 할때.. 먼저 RayCaster 객체를 하나 정의하구요.
_setupPicking() { const raycaster = new THREE.Raycaster(); this._divContainer.addEventListener("click", this._onClick.bind(this)); this._raycaster = raycaster; }
클릭 이벤트인 _onClick은 다음과 같습니다.
_onClick(event) { if(!event.ctrlKey) return false; const width = this._divContainer.clientWidth; const height = this._divContainer.clientHeight; const xy = {x: (event.offsetX / width) * 2 - 1, y: -(event.offsetY / height) * 2 + 1}; this._raycaster.setFromCamera(xy, this._camera); const targets = this._raycaster.intersectObjects(this._scene.children); if(targets.length > 0) { const mesh = targets[0].object; this._zoomFit(mesh, "Y", true, 50); } }
이 애니메이션 ZoomIn 기능을 이용해 만든 단위 기능에 대한 예제 영상은 다음과 같습니다.