Search code examples
javascriptaudioaframe

A-Frame - playing / pausing sound with a custom ('a-sound') source


Edit 2: Here is the working code. Many thanks to Piotr for his help I couldn't have done it so effortlessly without you guys.

sceneEl.querySelector('a-sound').setAttribute('sound', {src:url3}); 
      let playing = false;
      var el = document.querySelector('a-box');
      let audioEl = document.querySelector("a-sound");
      var audio = audioEl.components.sound;
      el.addEventListener('click', () => {
      if (!playing) {
      audio.playSound();
      } else {
      audio.stopSound();
      }
      playing = !playing;
      })


      } );
      request.send( null );
      }
      });

Edit: I've got the sound playing from a dynamic URL (in my JSON file), but I cant seem to get the event listener function right (for playing / pausing on click).

sceneEl.querySelector('a-sound').setAttribute('sound', {src:url3}); 
      let audioEl = document.querySelector("a-sound");
      let audio = audioEl.components.sound;
      sceneEl.querySelector('a-box').addEventListener('click', function () {
      if(!playing) {
          audio.play();
       } else {
          audio.pause();
          audio.currentTime = 0;
       }
       playing = !playing;
       });   
    } );
      request.send( null );
      }
      });

Original: I'm using this component in A-Frame, but I'm looking to play the sound from the src in the ('a-sound') entity rather than from the asset link. The reason is because I'm loading the sound files dynamically from a JSON array so they don't exist in any list of assets. I've got all my files loading but am having trouble getting this component to hook into my loaded sceneEl.querySelector('a-sound').setAttribute('sound', {src:url3}); code. I'm thinking its just a small syntax issue but I'm not 100% sure. Could someone please look over this for a minute and tell me if its doable? This is the code (same as the link except for the (a-sound) within the querySelector.

       AFRAME.registerComponent('audiohandler', {
       init:function() {
       let playing = false;
       let audio = document.querySelector('a-sound');
       this.el.addEventListener('click', () => {
       if(!playing) {
          audio.play();
       } else {
          audio.pause();
          audio.currentTime = 0;
       }
       playing = !playing;
       });
       }
       })
    </script> 

Solution

  • Using the <a-sound> You must handle things a bit differently.

    playing / stopping the sound should be done within the sound component. You need to access it via yourEntityName.components.sound and use the playSound() and stopSound() methods.

    check it out on my glitch. I set the source via the setAttribute(), and make a play / stop button.


    My <a-sound> has a geometry to be a button, but You can make a <a-sound> entity, and use it like this:

    let audioEl = document.querySelector("a-sound");
    audioEl.setAttribute("src", "sourceURL");
    
    let audio = audioEl.components.sound;
    // play = audio.playSound();
    // stop = audio.stopSound():
    

    Furthermore, there are many issues with the nodes not being fully loaded. Check out this example:

    <a-entity component></a-entity>
    <a-sound></a-sound>
    

    If the component tries to grab a reference to the document.querySelector("a-sound").components.sound, it may be undefined. If so, You should try to wait until it emits the loaded signal.