【问题标题】:Handling GearVR Controller events in AFrame在 AFrame 中处理 GearVR 控制器事件
【发布时间】:2018-01-12 02:57:52
【问题描述】:

所以,我应该从警告开始,我是 AFrame 的新手(尽管不是编程、游戏编程或 Javascript)。我目前正在尝试用基本的 GearVR 控制器交互组合一个简单的场景。

当我说“基本交互”时,我的意思是当你关注 official tutorial 时,我有一个小的启动场景,我只是想扩展它,这样当你按下触发器时,(特别是触发器,而不仅仅是任何按钮),小文本组件的文本值已更改。

长话短说——我的代码不起作用。尽管我在组件 init 函数中添加了事件侦听器(并且我已经确认正在调用 init),但似乎从未调用过侦听器回调。如果我不得不猜测,我会说我附加“激光控制”的实体没有发出“触发”事件,但我不确定如何确认。以下是相关部分:

AFRAME.registerComponent('gearvr-trigger', {
  schema: {
    textValue: {
      default: "Hello WebVR!"
    }
  },

  init: function() {
    var message_box = document.querySelector('#message');
    var el = this.el;

    el.addEventListener('triggerdown', function(evt) {
      message_box.setAttribute('value', this.data.textValue);
    });

  }


});
  <a-text id='message' value="Hello, A-Frame!" color="#BBB"
    position="-0.9 0.2 -3" scale="1.5 1.5 1.5">
  </a-text>


<a-box gearvr-trigger='textValue: "New Text Value";' src='#boxTexture' position='0 2 -5' rotation='0 45 45' scale='2 2 2'>
  <a-animation attribute='position' to='0 2.5 -5' direction='alternate' dur='2000' repeat='indefinite'></a-animation>
  <a-animation attribute="scale" begin="mouseenter" dur="300" to="2.3 2.3 2.3"></a-animation>
  <a-animation attribute="scale" begin="mouseleave" dur="300" to="2 2 2"></a-animation>
  <a-animation attribute="rotation" begin="click" dur="2000" to="360 405 45"></a-animation>
</a-box>
<a-entity raycaster='far: 100; showLine: true;' line='color: red;' laser-controls></a-entity>

如果比我更有经验的人看到我做错了什么,那就太好了,但如果你能指出一些响应 GearVR 控制器事件的​​体面代码示例,我也会很高兴。

【问题讨论】:

  • 他们需要指向盒子并按下扳机,还是只需要在指向任何地方时按下扳机?

标签: aframe


【解决方案1】:

正如其他人所指出的,您没有在自定义组件中选择 'triggerdown' 事件的原因是这些事件是由控制器实体(在本例中为 a-entity[laser-controls])发出的,它们就像在标准 DOM,(在这种情况下将在 a-scene 旁边),所以 a-box 没有看到它们。

当您结合有关控制器按钮的信息以及控制器与场景中其他实体的关系(例如,用激光指向或碰撞)时,我喜欢将其称为手势。 laser-controls 组件提供基本的手势解释,但我创建了 super-hands package for rich gesture interpretation,包括您需要的:按钮识别。

<html>
<head>
<script src="https://aframe.io/releases/0.7.1/aframe.min.js"></script>
<script src="https://unpkg.com/super-hands/dist/super-hands.min.js"></script>
<script>
AFRAME.registerComponent('gearvr-trigger', {
  schema: {
    textValue: {
      default: "Hello WebVR!"
    }
  },

  init: function() {
    var message_box = document.querySelector('#message');
    var el = this.el;
    var triggerResponse = function (evt) {
      if (evt.detail.state === 'clicked') {
        message_box.setAttribute('value', this.data.textValue);
      }
    }
    el.addEventListener('stateadded', triggerResponse.bind(this));

  }

});
</script>
</head>
<body>
<a-scene>
<a-assets>
  <a-mixin id="point-laser" raycaster='far: 100; showLine: true;' line='color: red;'></a-mixin>
</a-assets>
<a-text id='message' value="Hello, A-Frame!" color="#BBB"
    position="-0.9 0.2 -3" scale="1.5 1.5 1.5">
  </a-text>


<a-box clickable="startButtons: triggerdown, mousedown; endButtons: triggerup, mouseup" gearvr-trigger='textValue: "New Text Value";' src='#boxTexture' position='0 2 -5' rotation='0 45 45' scale='2 2 2'>
  <a-animation attribute='position' to='0 2.5 -5' direction='alternate' dur='2000' repeat='indefinite'></a-animation>
  <a-animation attribute="scale" begin="hover-start" dur="300" to="2.3 2.3 2.3"></a-animation>
  <a-animation attribute="scale" begin="hover-end" dur="300" to="2 2 2"></a-animation>
  <a-animation attribute="rotation" begin="grab-end" dur="2000" to="360 405 45"></a-animation>
</a-box>
<a-entity progressive-controls="maxLevel: point; pointMixin: point-laser" ></a-entity>
</a-scene>
</body>
</html>

对于控制器,progressive-controls 自动检测控制器并像laser-controls 一样设置激光指示器,但使用super-hands 手势解释(它还为桌面/纸板用户提供类似光标的输入)。

<a-entity progressive-controls="maxLevel: point; pointMixin: point-laser"></a-entity>

对于目标实体,clickable 将其激活为手势接收组件,并定义它将接受哪些按钮事件(如果您不想要跨平台支持,可以移除鼠标事件)。动画触发事件也更新了aa 以使用super-hands

<a-box clickable="startButtons: triggerdown, mousedown; endButtons: triggerup, mouseup" gearvr-trigger='textValue: "New Text Value";' ...>
...
<a-animation attribute="scale" begin="hover-start" dur="300" to="2.3 2.3 2.3"></a-animation>
<a-animation attribute="scale" begin="hover-end" dur="300" to="2 2 2"></a-animation>
<a-animation attribute="rotation" begin="grab-end" dur="2000" to="360 405 45"></a-animation>

对于您的自定义反应组件,我对其进行了更改以对状态变化做出反应,这就是clickable 如何传达已收到可接受的手势。我还解决了一个范围界定问题,一旦你有事件触发它,你就会发现这个问题。

    var triggerResponse = function (evt) {
      if (evt.detail.state === 'clicked') {
        message_box.setAttribute('value', this.data.textValue);
      }
    }
    el.addEventListener('stateadded', triggerResponse.bind(this));

【讨论】:

  • 这个线程上的所有其他答案都很好,但这个是最彻底的。我一定会检查超级手!
【解决方案2】:

试试 setAttribute('text', 'value, 'whatever you want') ?

【讨论】:

  • 这就是这个位正在做的事情:el.addEventListener('triggerdown', function(evt) { message_box.setAttribute('value', this.data.textValue); });
  • 此外,triggerdown 事件可能会在附加了激光控件的实体上触发,这不是您的消息框实体
  • 对,我想我应该更清楚地知道这里应该发生什么。在场景中,有一个漂浮的立方体。指向立方体并触发后,我希望看到更新的文本消息。因此,我将组件附加到将被单击的多维数据集上,然后进行 DOM 查找以查找文本。
  • 看起来你在 a-box 上有 triggerdown 监听器,但没有带有激光控制的 a-entity...我可能记错了,但我似乎记得那个光标的事件/raycaster 在相交元素上触发不是触发,而是(最终)单击...
  • triggerdown 事件将在具有激光控制(获得 gearvr 控制)的实体上触发。但是你想要到达目标的事件,如果你查看激光控制使用的光标组件的文档,你会明白我所说的点击
【解决方案3】:

如果不是触发代码,则可能是范围问题: 'this' 指的是处理程序中的元素而不是组件,因此 this.data 在事件期间是未定义的

一个潜在的修复:

AFRAME.registerComponent('gearvr-trigger', {
  schema: {
    textValue: {
      default: "Hello WebVR!"
    }
  },

  init: function() {
    var message_box = document.querySelector('#message');
    var el = this.el;

    var self = this;
    el.addEventListener('triggerdown', function(evt) {
      message_box.setAttribute('value', self.data.textValue);
    });
  }
});

或使用箭头函数

AFRAME.registerComponent('gearvr-trigger', {
  schema: {
    textValue: {
      default: "Hello WebVR!"
    }
  },

  init: function() {
    var message_box = document.querySelector('#message');
    var el = this.el;

    el.addEventListener('triggerdown', (evt) => {
      message_box.setAttribute('value', this.data.textValue);
    });
  }
});

【讨论】:

    【解决方案4】:

    triggerdown 事件在具有激光控制属性的实体上触发。

    我的代码使用click 事件并响应任一按钮按下(与您想要的不同),但实现此模式可能会推动您前进。 (它也更多是在跨设备操作的路径上。)click 事件可能包含按下了哪个按钮。

    在场景中,我有:

    &lt;a-entity laser-controls="hand: right"&gt;&lt;/a-entity&gt;

    在脚本中,我注册

        AFRAME.registerComponent('cursor-listener', {
            init: function () {
                var lastIndex = -1;
                var COLORS = ['purple', 'orange', 'white'];
                this.el.addEventListener('click', function (evt) {
                    lastIndex = (lastIndex + 1) % COLORS.length;
                    this.setAttribute('material', 'color', COLORS[lastIndex]);
                    console.log('I was clicked at: ', evt.detail.intersection.point);
                });
            }
        });
    

    然后我在目标框上设置cursor-listener属性:

    boxEl.setAttribute('cursor-listener', true);

    【讨论】:

    • 这绝对让我更接近了......至少在按下顶部按钮时我得到了对“点击”事件的响应的意义上。尽管如此,触发器仍然被完全忽略 - 它甚至没有被视为点击。需要明确的是——我知道触发器通常可以工作,我一直都在使用它。
    • 是的,我忘了激光控制只使用触摸板按钮。您可能想要使用激光控制,并对其进行猴子补丁以使用触发器。或者将按钮配置添加到激光控件,然后提交拉取请求。
    • 实际上,在稍微摆弄了一些东西并意识到我的错误之后,我发现我能够使用激光控制来触发触发,如果你考虑一下,这是有道理的Laser-controls 组件确实在幕后设置了 gearvr-controls。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-15
    相关资源
    最近更新 更多