Как отключить событие щелчка raycaster для объекта в Aframe?

Я хочу отключить щелчок по объекту после того, как Raycaster щелкнул его один раз. Сущность открывает панель, поэтому я не хочу, чтобы она отображалась более одного раза


person piede    schedule 23.04.2018    source источник


Ответы (1)


Это действительно зависит от того, используете ли вы raycaster="objects: ...;". Обычно это рекомендуемый подход, поэтому ваш Raycaster не взаимодействует с каждым объектом в сцене, вызывая падение производительности.

Это можно сделать разными способами, но одним из наиболее распространенных является использование селектора классов, например .clickable, а затем удаление этого класса при нажатии. Затем удалите прослушиватель событий, если он больше не нужен.

Курсор Raycaster:

<a-cursor raycaster="objects: .clickable;"></a-cursor>

Компонент:

AFRAME.registerComponent('click-once', {
  init: function () {
    var self = this;
    var scene = self.el.sceneEl;
    var raycaster = scene.querySelector('[cursor]').components.raycaster;

    // Define function to be executed on click.
    var clickHandler = function (e) {

      // Log clicks.
      console.log('clicked');

      // Remove "clickable" class from entity.
      self.el.classList.remove('clickable');

      // Refresh raycaster object list to reflect changes.
      raycaster.refreshObjects();

      // Remove event listener since no longer needed.
      self.el.removeEventListener('click', clickHandler);

    };

    // Add event listener for click.
    self.el.addEventListener('click', clickHandler);
  }
});   

РЕДАКТИРОВАТЬ: Это можно упростить еще больше, если в качестве селекторов используются data-xxxx атрибуты или компоненты, а не классы / идентификаторы. Например: data-clickable

По умолчанию raycaster в A-Frame автоматически обновляется при добавлении / удалении сущностей и атрибутов / компонентов (не классов), поэтому в этом случае нет необходимости использовать raycaster.refreshObjects(). https://aframe.io/docs/master/components/raycaster.html#properties_autorefresh

HTML:

<a-entity cursor raycaster="objects: [data-clickable];"></a-entity>

JS:

self.el.removeAttribute('data-clickable');

Демонстрация кода в действии: https://codepen.io/dansinni/pen/MGKGZq

РЕДАКТИРОВАТЬ: если вы используете <a-cursor>, а не <a-entity cursor="...", вам может потребоваться следующее назначение var raycaster:

var raycaster = scene.querySelector('a-cursor').components.raycaster;

Или, если вы явно присоединяете компонент raycaster:

var raycaster = scene.querySelector('[raycaster]').components.raycaster;

Надеюсь это поможет.

person Dan S.    schedule 23.04.2018
comment
Я использую этот код, и, похоже, он в основном работает, но я получаю эту ошибку: Uncaught TypeError: не удается прочитать свойство «refreshObjects» неопределенного значения. Я не уверен, почему он видит raycaster как undefined, но все еще работает. Любые идеи? - person schatzkin; 22.08.2018
comment
@schatzkin: Я обновил свой ответ, чтобы решить вашу проблему. Смотрите правку ближе к концу. - person Dan S.; 22.08.2018
comment
Я обновил свой ответ и демонстрацию, чтобы показать, как можно использовать атрибуты данных или компоненты, а не классы. Этот метод лучше, потому что нет необходимости вручную обновлять список объектов raycaster, поскольку A-Frame делает это автоматически по умолчанию при добавлении / удалении объектов, компонентов и определенных атрибутов (например, data-xxxx). - person Dan S.; 23.08.2018