I have an A-Frame project with multiple interactive buttons that lead to an audio source playing.
The issue is that the user can accidentally double click on the buttons and the audio will play again right after the original.
The user can also click on a different button and have a different audio play while the original is still playing.
What would be the best way to fix these issues?
Thanks!
<!--Teleportation-->
<a-entity position="-1.72 1.06 -2.57" class="teleport">
<a-box color="white" depth=".1" height=".1" width="0.3" color="white" rotation="-30 0 0" position="0 -.08 -.2">
<a-entity text="align: center; color:black;value: Teleport" position="-.02 0 0.05"></a-entity>
</a-box>
<a-cylinder position="0 -.17 0" color="yellow" height=".2" radius=".1"
sound__1="on: mouseenter; src: #teleportation-script;"
sound__2="on: click; src: #teleportation-script;"></a-cylinder>
</a-entity>
<!--Hyperdrive-->
<a-entity position="1.72 1.06 -2.57" class="hyperdrive">
<a-box color="white" depth=".1" height=".1" width="0.3" color="white" rotation="-30 0 0" position="0 -.08 -.2">
<a-entity text="align: center; color:black;value: Hyperdrive" position="-.02 0 0.05"></a-entity>
</a-box>
<a-entity gltf-model-next="#button" scale=".2 .2 .2" position="0 -.08 0"
sound__1="on: mouseenter; src: #hyperdrive-script;"
sound__2="on: click; src: #hyperdrive-script;">
</a-entity>
</a-entity>
<!--Comms-->
<a-entity position="-1.4 1.06 -1.6" class="comms">
<a-box color="white" depth=".1" height=".1" width="0.3" color="white" rotation="-30 0 0" position="0 -.08 -.2">
<a-entity text="align: center; color:black;value: Comms" position="-.02 0 0.05"></a-entity>
</a-box>
<a-entity gltf-model-next="#comms" scale=".05 .05 .05" rotation="0 45 0" position="0 -0.1 0.05"
sound__1="on: mouseenter; src: #comms-script;"
sound__2="on: click; src: #comms-script;"></a-entity>
</a-entity>
<!--Planetary Information-->
<a-entity position="-1.0 1.06 -2.07" class="planet">
<a-box color="white" depth=".1" height=".1" width="0.3" color="white" rotation="-30 0 0" position="0 -.08 -.2">
<a-entity text="align: center; color:black;value: Planet Info" position="-.02 0 0.05"></a-entity>
</a-box>
<a-triangle scale=".2 .2 .2" rotation="-90 0 0" color="orange" position="0.1 -.08 .10"
sound__1="on: mouseenter; src: #planet-info-script;"
sound__2="on: click; src: #planet-info-script;"></a-triangle>
</a-entity>
<!--Lasers-->
<a-entity position="1.4 1.06 -1.6" class='lasers'>
<a-sphere radius=".1" position="0 -.15 0" color="red"
sound__1="on: mouseenter; src: #lasers-script;"
sound__2="on: click; src: #lasers-script;"></a-sphere>
<a-box color="white" depth=".1" height=".1" width="0.3" color="white" rotation="-30 0 0" position="0 -.08 -.2">
<a-entity text="align: center; color:black;value: Lasers" position="-.02 0 0.05"></a-entity>
</a-box>
</a-entity>
This would be a good feature request for the a-frame sound component: To have a sound-started event, so that you could set a global isPlaying flag.
For a potential solution: It sounds like what you want is a global state that says if a sound can play or not.
I've written a sample custom component that could help: https://glitch.com/edit/#!/a-frame-singleton-sound?path=index.html:1:0
AFRAME.registerComponent('singleton-sound', {
schema: {
src: {type: 'string'}
},
init: function () {
var audio = document.querySelector(this.data.src);
this.el.addEventListener('click', playIfFree);
this.el.addEventListener('mouseenter', playIfFree);
audio.addEventListener('ended', function () {
window.isPlaying = false
})
function playIfFree () {
if(!window.isPlaying) {
audio.play();
window.isPlaying = true
} else {
return false
}
}
}
});
Then in use:
<a-sphere singleton-sound="src: #thunder;"></a-sphere>
If you preview the sample and hover over the blue box first, a 16s audio will play, if you hover over the red sphere in the meantime it won't play while the first one is still going. And vice versa.
When the sound ends, it sets the flag of window.isPlaying to false, so that the next event handler will be able to play its sound.