2

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> 
Piotr Adam Milewski
  • 14,150
  • 3
  • 21
  • 42

1 Answers1

2

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.

Piotr Adam Milewski
  • 14,150
  • 3
  • 21
  • 42
  • Thanks for the tip. I've applied some of your code and I can get sound to play from my dynamic source with that audio.playSound(); command, but the click function doesn't seem to be working. Can you check my edited post and see if you spot the problem? – Dario Silva Jan 06 '18 at 20:39
  • try document.querySelector, instead of sceneEl.querySelector. sceneEl is not defined anywhere. Moreover, do You have only on box on Your scene? – Piotr Adam Milewski Jan 06 '18 at 20:43
  • Yeah I only have one box for now. I defined the sceneEl earlier in the component. Seems that document.querySelector doesn't make it work either. It works if its set to autoplay so I know the URL part is working. Any ideas? – Dario Silva Jan 06 '18 at 20:55
  • is it similar to my [fiddle](https://jsfiddle.net/0wuLh0d4/1/) ? maybe the sound node isn't fully loaded, when You do the `init()` in `audiohandler`. Try putting `` as Your first entity ( bad workaround, but if it works, You could try listening for the `loaded` event, and then set any other listeners) – Piotr Adam Milewski Jan 06 '18 at 20:59
  • @DarioSilva I've made an update with listening for the a-sound to load https://jsfiddle.net/0wuLh0d4/4/ – Piotr Adam Milewski Jan 06 '18 at 21:05
  • I'm not using the audiohandler because it doesnt pick up my dynamic URL. I updated the original code in the question to show what it looks like now. – Dario Silva Jan 06 '18 at 21:07
  • Do You wrap Your code in a `window.onload = function(){}` function ? otherwise the a-frame nodes may not be loaded when Your code is executed ( check out the updated fiddle https://jsfiddle.net/0wuLh0d4/6/) – Piotr Adam Milewski Jan 06 '18 at 21:14
  • Thats an interesting point. I have a request.addEventListener( 'load', function ( event ) near the beginning of the component, but I tried the window.onload function now as well. I placed it between the first and second line of the code in my question (and had to add an extra } symbol. – Dario Silva Jan 06 '18 at 21:21
  • @DarioSilva when the request is loaded, the a-sound may not be fully loaded, so the a-sound.components.sound is undefined / null. Thats why I placed it in a window.onload – Piotr Adam Milewski Jan 06 '18 at 21:23
  • Your code is working. I found a 'let' instead of a 'var' that seemed to be causing issues. Will post updated code once I check it a bit more. – Dario Silva Jan 06 '18 at 21:41
  • This is great, thanks for posting. I'm wondering how to best configure the code for multiple objects, each having their own sound file. – schatzkin Aug 27 '18 at 23:20