three.js之模型区域选中方法

今天从ui那边拿到一个城镇模型,样子长这样的

three.js之模型区域选中方法

3d模型

要实现的效果是选择这个模型中的某个房子,实现交互。效果如下

three.js之模型区域选中方法

交互效果

导入模型和可能遇到的问题

可以对模型的大小进行了缩放,并且通过计算xyz的最远和最近的2点确定中心点,将模型放置在视图的中心位置。核心代码如下:

objLoader.load('./obj/house.obj', function (obj) { 		console.log(obj) 		obj.traverse(function (child) { 			if (child instanceof THREE.Mesh) { 				child.material = new THREE.MeshLambertMaterial({ 					color: 0x2397F6, 					side: THREE.DoubleSide 				}); 			} 		});  		obj.scale.set(0.05, 0.05, 0.05) 		var box = new THREE.Box3(); 		box.expandByObject(obj);  		var x = (box.max.x + box.min.x) / 2; 		var y = (box.max.y + box.min.y) / 2; 		var z = (box.max.z + box.min.z) / 2;  		obj.position.set(0 - x, 0 - y, 0 - z);  		obj.castShadow = true; 		obj.receiveShadow = true;  		let wrapper = new THREE.Object3D(); 		//模型在场景中实际位置 		var pt = { 			x: 0, 			y: 0, 			z: 0 		}; 		wrapper.position.set(pt.x, pt.y, pt.z); 		wrapper.add(obj); 		scene.add(wrapper); 		render(); 	});

点击事件

three.js通过射线检测我们所点击的对象。

这里我们需要将鼠标的x,y点转化为空间坐标。这里简单地讲下原理(不想看的也可以跳过,直接拷贝公式)。

原理

x = event.clientX  // 鼠标点击的位置 x1=x-window.innerWidth/2; // (减去空间坐标原点) a=x1/(window.innerWidth/2)  // (空间坐标在[-1,1]之间,window.innerWidth/2  代表长度1) // 化简后得到 a=(event.clientX / window.innerWidth) * 2 - 1

three.js之模型区域选中方法

分析图

点击事件代码

const onMouseMove = (event) => { 		// 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1) 		this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1 		this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1  		tooltip.style.left = event.clientX + 2 + 'px' 		tooltip.style.top = event.clientY - 200 + 'px' 		animate() 	}  	window.addEventListener('mousedown', onMouseMove, false)  	var lastPick = null  	function animate() { 		// 通过摄像机和鼠标位置更新射线 		raycaster.setFromCamera(mouse, camera) 		// 算出射线 与当场景相交的对象有那些 		const intersects = raycaster.intersectObjects( 			scene.children, 			true 		) 		// 恢复上一个模型状态 		if (lastPick) { 			this.tooltip.style.visibility = 'hidden' 			this.lastPick.object.material.color.set('#2397F6') 		} 		lastPick = intersects.find( 			(item) => { 				return item 			} 		) 		if (lastPick) {       // 模型状态修改 			console.log(this.lastPick.object.name) 			this.lastPick.object.material.color.set('red')       // 这里的模型名称是ui做3d时候命名的,可以自定义修改 			this.tooltip.innerHTML = '模型名称:' + this.lastPick.object.name 			this.tooltip.style.visibility = 'visible'  		} 		render() 	}

结语

以上就是所有的核心代码。对于模型要求整体性要高一点,不能太零散,否则会出行点击高楼时候,出现了避雷针没有被选中现象。

前端3D模型交互
分享到:

您可能还会对下面的文章感兴趣: