A-Frame Components
draggable-by-ray:利用手柄射线拽取实体
-
全局定义
-
增加组件依赖,或另外挂载在 a-entity 上
-
raycaster 事件属性方法详见:https://aframe.io/docs/1.5.0/components/raycaster.html#members
dependencies: ["raycaster"];
- 设置参数及默认值
schema: { speed: { type: "number", default: 5 }, // 移动速度,默认为5米/秒 minDistance: { type: "number", default: 0.2 }, // 最小距离,默认为0.2米 },
- 全局变量
init: function () { var self = this; // 存储选中的实体 this.selectedEntity = null; // 是否按下trigger this.isTriggerDown = null; }
-
-
监听手柄 trigger 事件:根据手柄 trigger 事件激活拉取动作
// 监听trigger按下事件 this.el.addEventListener("triggerdown", function () { self.isTriggerDown = true; }); // 监听trigger释放事件 this.el.addEventListener("triggerup", function () { self.isTriggerDown = false; });
-
监听 raycaster 指向事件:更新 raycaster 指向的对象实体
// 监听 raycaster 指向事件 this.el.addEventListener("raycaster-intersection", function (evt) { // 获取选中的第一个实体 self.selectedEntity = evt.detail.els[0]; }); // 监听 raycaster 离开事件,取消选中的实体 this.el.addEventListener("raycaster-intersection-cleared", function () { self.selectedEntity = null; });
-
tick 渲染
-
判别是否存在选中的实体、是否按下 trigger
-
获取手柄位置(终点)
-
计算移动方向,移动距离,并移动到目标位置
-
判断终点距离 minDistance,小于 minDistance 则不进行移动
-
根据方向向量进行每帧平滑移动
tick: function (time, timeDelta) { // 如果存在选中的实体,则平滑移动到手柄位置 if (this.selectedEntity && this.isTriggerDown) { // 获取目标位置(手柄位置) var targetPosition = this.el.object3D.position.clone(); // 获取起始位置(选中实体的位置) var currentPosition = this.selectedEntity.object3D.position.clone(); //计算两者距离 var distance = currentPosition.distanceTo(targetPosition); // 如果距离小于最小距离,不进行移动 if (distance < this.data.minDistance) { return; } // 计算移动方向 // 计算三维坐标差,并进行.normalize()归一化,得到单位方向向量 var direction = targetPosition.clone().sub(currentPosition).normalize(); // 计算移动距离 var moveDistance = this.data.speed * (timeDelta / 1000); // 计算目标位置:当前位置+方向向量*移动距离 // .multiplyScalar():将向量乘以一个标量,返回一个新的向量。 var newPosition = currentPosition .clone() .add(direction.multiplyScalar(moveDistance)); // 设置实体的新位置 this.selectedEntity.setAttribute("position", newPosition); } }
-
-
HTML 示例
<a-scene> <a-camera position="0 1.6 0"></a-camera> <a-entity id="leftHand" oculus-touch-controls="hand: left"></a-entity> <!-- draggable-by-ray挂载 --> <a-entity id="rightHand" laser-controls="hand:right" raycaster="objects: .draggable; far: 10" draggable-by-ray ></a-entity> <!-- 设置raycaster的objects类型为draggable --> <a-box class="draggable" id="box" position="1 1 -6" color="#4CC3D9" ></a-box> <a-box class="draggable" id="box" position="-1 2 -4" color="#FF0000" ></a-box> </a-scene>