Threejs根据鼠标动态改变controls的target(缩放中心点)

本文介绍了如何在Threejs中根据鼠标位置动态改变controls的target,以实现更灵活的缩放交互效果。通过对比普通缩放和优化后的缩放操作,展示了这种交互方式的差异,并提供了相关代码参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

好久没更新博客了,记下一笔
最近看到很多公司的产品的鼠标交互部分,controls的缩放中心不是固定的,比如这个,这个鼠标的交互方式跟我们平常用到的OrbitControls或者TrackballControls都不一样,特别是缩放时,它的target不是固定的,最近研究了一下:
废话不多说,先上图:
普通的缩放操作 普通的缩放操作
这里写图片描述 优化后的缩放操作
代码如下:

$('body').on('mousewheel', function ( ev ){

        var factor = 3;

       
<think>好的,我现在需要帮助用户在Vue3中使用Three.js的OrbitControls实现以鼠标位置为中心的缩放功能。首先,我需要回顾一下OrbitControls的基本原理。根据引用[2],OrbitControls通过控制摄像机与模型的距离来实现旋转、缩放等功能。通常,默认的缩放可能以画布中心为中心,但用户希望以鼠标位置为中心缩放,这需要调整摄像机的位置和观察点。 接下来,我应该考虑如何修改OrbitControls的默认缩放行为。OrbitControls本身可能没有直接提供以鼠标为中心缩放的选项,因此需要手动干预缩放过程。根据引用[1]中的例子,鼠标位置可以通过事件监听获取,比如event.pageX和event.pageY。但需要注意,Three.js中的坐标系统与屏幕坐标可能不同,需要进行转换。 然后,我需要确定缩放时如何调整摄像机的位置。以鼠标位置为中心缩放意味着在缩放时,摄像机需要朝着鼠标所在的三维点移动,而不仅仅是向场景中心移动。这涉及到将鼠标的屏幕坐标转换为场景中的三维坐标,可能需要使用射线投射(Raycaster)来获取鼠标指向的三维点。 另外,引用[3]提到了在animate函数中设置camera.lookAt,这可能对保持观察方向有帮助。在缩放过程中,可能需要动态调整摄像机的位置,同时保持看向某个点,以确保视角正确。 可能的步骤包括: 1. 监听鼠标滚轮事件,获取鼠标在屏幕上的位置。 2.鼠标位置转换为Three.js的三维坐标,找到鼠标指向的场景中的点。 3. 根据缩放方向(放大或缩小),计算摄像机需要移动的距离。 4. 调整摄像机的位置,使其朝向鼠标点移动,同时保持观察目标。 5. 更新OrbitControls的目标点,可能需要禁用自动旋转或其他默认行为。 需要注意的是,直接修改OrbitControls的内部方法可能会比较困难,因此可能需要覆盖或扩展其缩放处理逻辑。此外,在Vue3中集成时,要确保正确管理事件监听器和Three.js对象的生命周期,避免内存泄漏。 最后,测试实现的效果,确保缩放平滑且以鼠标位置为中心,同时处理可能的边缘情况,比如鼠标在画布边缘时的坐标转换问题。</think>在Vue3中实现Three.js的OrbitControls鼠标位置为中心的缩放功能,需要重写缩放逻辑并处理坐标转换。具体步骤如下: --- ### 1. 禁用默认缩放行为 首先禁用OrbitControls的默认缩放响应: ```javascript import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' const controls = new OrbitControls(camera, renderer.domElement) controls.enableZoom = true // 保持缩放功能启用 controls.mouseButtons.LEFT = null // 禁用左键旋转 ``` --- ### 2. 监听鼠标滚轮事件 通过自定义滚轮事件实现精准控制: ```javascript let targetZoom = 1 // 当前缩放系数 const ZOOM_SPEED = 0.1 renderer.domElement.addEventListener('wheel', (event) => { event.preventDefault() // 获取标准化鼠标位置(范围[-1,1]) const mouse = new THREE.Vector2() mouse.x = (event.offsetX / window.innerWidth) * 2 - 1 mouse.y = -(event.offsetY / window.innerHeight) * 2 + 1 // 计算缩放方向 const delta = event.deltaY > 0 ? 1 : -1 targetZoom *= Math.pow(0.95, delta * ZOOM_SPEED) // 执行自定义缩放 handleZoom(mouse, delta) }) ``` --- ### 3. 实现坐标转换与缩放 核心算法通过射线投射获取三维空间坐标点: ```javascript const raycaster = new THREE.Raycaster() const targetPoint = new THREE.Vector3() function handleZoom(mouse, delta) { // 获取鼠标指向的三维坐标 raycaster.setFromCamera(mouse, camera) const intersects = raycaster.intersectObjects(scene.children) if (intersects.length > 0) { targetPoint.copy(intersects[0].point) } else { // 当未选中物体时,使用默认场景中心点 targetPoint.set(0, 0, 0) } // 计算摄像机位移方向 const direction = new THREE.Vector3() direction.subVectors(camera.position, targetPoint).normalize() // 计算新摄像机位置 const newPosition = new THREE.Vector3() const moveDistance = direction.multiplyScalar(delta * ZOOM_SPEED) newPosition.copy(camera.position).add(moveDistance) // 更新摄像机 camera.position.copy(newPosition) controls.target.copy(targetPoint) // 关键:更新控制器的目标点[^2] controls.update() } ``` --- ### 4. 在Vue组件中的集成 在Vue3组件中管理Three.js生命周期: ```vue <script setup> import { onMounted, onUnmounted } from 'vue' let controls, renderer, camera onMounted(() => { // 初始化Three.js场景 initScene() // 初始化轨道控制器 controls = new OrbitControls(camera, renderer.domElement) controls.minDistance = 2 controls.maxDistance = 50 }) onUnmounted(() => { // 清理事件监听器 renderer.domElement.removeEventListener('wheel', handleWheel) }) </script> ``` --- ### 实现原理 1. **坐标转换**:通过`Raycaster`将2D屏幕坐标转换为3D场景坐标[^1] 2. **摄像机移动**:根据鼠标指向点计算摄像机位移方向,保持观察焦点始终在目标点[^2] 3. **控制器同步**:每次缩放后强制更新`controls.target`确保控制器状态同步[^3] ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值