You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

A-Frame鼠标滚轮拖动盒子位置重置问题修复咨询

鼠标滚轮拖动移动物体位置重置问题修复

问题描述

已实现按下鼠标滚轮拖动鼠标改变物体位置的功能,但两次滚轮点击之间移动鼠标时,盒子位置会被重置。需求是按下滚轮拖动时,盒子从当前位置平滑移动到目标位置。

问题根源

  1. 滚轮按下时未初始化鼠标起始位置(x_cord/y_cord),导致第一次鼠标移动的位移计算错误
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 03:42:20