Search code examples
javascripteventsaframeraycastingwebvr

How do I disable the raycaster click event on an a-entity in Aframe?


I want to disable the click on an entity after it's been clicked once by the raycaster. The entity opens up a panel so I don't want it to show more than once


Solution

  • This really depends whether or not you're using raycaster="objects: ...;". This is usually the recommended approach so your raycaster isn't interacting with every entity in the scene causing a drop in performance.

    This can be done many ways, but one of the most common is to use a class selector like .clickable and then remove that class upon click. Then remove the event listener if it is no longer needed.

    Cursor Raycaster:

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

    Component:

    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);
      }
    });   
    

    EDIT: This can be simplified even further if data-xxxx attributes or components are used as selectors, rather than classes/ids. E.g.: data-clickable

    By default, A-Frame's raycaster automatically refreshes when entities and attributes/components (not classes) are added/removed, so there is no need to use raycaster.refreshObjects() in this case. 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');
    

    Demo of the code in action: https://codepen.io/dansinni/pen/MGKGZq

    EDIT: If you are using <a-cursor> rather than <a-entity cursor="...", then you may need to use the following var raycaster assignment:

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

    Or, if you are attaching the raycaster component explicitly:

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

    Hope this helps.