A-Frame鼠标滚轮拖动盒子位置重置问题修复咨询
鼠标滚轮拖动移动物体位置重置问题修复
问题描述
已实现按下鼠标滚轮拖动鼠标改变物体位置的功能,但两次滚轮点击之间移动鼠标时,盒子位置会被重置。需求是按下滚轮拖动时,盒子从当前位置平滑移动到目标位置。
问题根源
- 滚轮按下时未初始化鼠标起始位置(
x_cord/y_cord),导致第一次鼠标移动的位移计算错误 targetPosition变量未在滚轮按下时赋值为物体当前位置,后续位移计算失去基准
修复方案
修改组件的OnDocumentMouseDown和OnDocumentMouseMove方法,确保滚轮按下时记录正确的起始状态,拖动时基于初始位置计算位移:
<html> <head> <title>Rotation, Zoom et Déplacement</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <script src="https://aframe.io/releases/0.4.0/aframe.min.js"></script> </head> <body> <script type="text/javascript"> AFRAME.registerComponent('drag-rotate-move-component', { schema: { speed: { default: 4 }, zoomSpeed: { default: 0.5 }, moveSpeed: { default: 0.01 } // 移动速度设置 }, init: function () { this.ifMouseDown = false; this.ifMiddleMouseDown = false; // 中键按下状态标记 this.x_cord = 0; this.y_cord = 0; this.targetPosition = new THREE.Vector3(); // 物体初始位置记录 document.addEventListener('mousedown', this.OnDocumentMouseDown.bind(this)); document.addEventListener('mouseup', this.OnDocumentMouseUp.bind(this)); document.addEventListener('mousemove', this.OnDocumentMouseMove.bind(this)); document.addEventListener('wheel', this.OnDocumentMouseWheel.bind(this)); document.addEventListener('contextmenu', function (e) { e.preventDefault(); }); // 禁用右键菜单 }, OnDocumentMouseDown: function (event) { if (event.button === 0) { this.ifMouseDown = true; this.x_cord = event.clientX; this.y_cord = event.clientY; } else if (event.button === 1) { this.ifMiddleMouseDown = true; // 滚轮按下时,记录当前鼠标位置和物体初始位置 this.x_cord = event.clientX; this.y_cord = event.clientY; this.targetPosition.copy(this.el.object3D.position); } }, OnDocumentMouseUp: function (event) { if (event.button === 0) { this.ifMouseDown = false; } else if (event.button === 1) { this.ifMiddleMouseDown = false; } }, OnDocumentMouseMove: function (event) { if (this.ifMouseDown) { var temp_x = event.clientX - this.x_cord; var temp_y = event.clientY - this.y_cord; if (Math.abs(temp_y) < Math.abs(temp_x)) { this.el.object3D.rotateY(temp_x * this.data.speed / 1000); } else { this.el.object3D.rotateX(temp_y * this.data.speed / 1000); } this.x_cord = event.clientX; this.y_cord = event.clientY; } else if (this.ifMiddleMouseDown) { // 计算鼠标位移 var deltaX = event.clientX - this.x_cord; var deltaY = event.clientY - this.y_cord; // 基于物体到初始位置的距离调整移动幅度 var distance = this.el.object3D.position.distanceTo(this.targetPosition); var factor = distance / 500; var moveX = deltaX * factor * this.data.moveSpeed; var moveY = deltaY * factor * this.data.moveSpeed; // 从初始位置出发计算新位置 this.el.object3D.position.x = this.targetPosition.x + moveX; this.el.object3D.position.y = this.targetPosition.y - moveY; // 反转Y轴方向匹配鼠标移动 // 更新当前鼠标位置 this.x_cord = event.clientX; this.y_cord = event.clientY; } }, OnDocumentMouseWheel: function (event) { var delta = event.deltaY; var scale = 1 + delta * this.data.zoomSpeed / 1000; this.el.object3D.scale.multiplyScalar(scale); } }); </script> <a-scene> <a-box id="b1" color="green" position="2 2 -3" drag-rotate-move-component></a-box> <a-box id="b2" color="blue" position="-2 2 -3"></a-box> <a-camera position="0 0 0" look-controls="enabled:false"> <a-cursor></a-cursor> </a-camera> </a-scene> </body> </html>
关键修改点
- 滚轮按下时,将
targetPosition设为物体当前位置,同时初始化x_cord和y_cord为当前鼠标坐标 - 拖动时基于
targetPosition(初始位置)和鼠标位移计算新位置,而非累加位移,避免重置问题 - 引入
moveSpeed参数控制移动灵敏度,让调整更直观
内容的提问来源于stack exchange,提问作者karl thomas
相关产品推荐
相关产品推荐

