How to control Audio with keyboard keys?


(Matt) #1

I have attached a hype document here. The elements when clicked will trigger an audio file.

Does anyone know how I might use javascript to have specific computer keys trigger each of the audio files? (It would be a bonus if when the key is clicked there would also be a slight visual indication on the element)

Thank you!
Chords Demo.hype.zip (1.3 MB)


#2

Hi Matt:

Here’s a technique to run functions when a keypress has occurred: Howto: Navigate Scenes with Arrow Keys (Similar to a Powerpoint or Keynote Presentation)
You can combine those scripts with the audio control code listed here: Controlling Audio & Advanced Techniques (Play, Pause, Rewind, Volume control)


(Matt) #3

Thanks. Do you know if this will function properly if my Hype content is embedded in an iFrame?


#4

This would require that the iframe had focus, since keypresses can only be captured by the active window. To make a window ‘active’ the visitor would need to click on it (within the iframe), then use a keypress action.


(Mark Hunte) #5

I wonder if the main window can capture the keypress and pass the event on to the iframe.

You may then need to do a if clause in the iFrame to determine where it is getting the event from and act accordingly i.e the iframe was the one who get the event while in focus.


(Matt) #6

Thanks for this. I’m still having trouble just getting my sound to play with a key click.
I’ve been able to recreated the swap scenes but not play audio.

I’m running this on Scene Load

	document.onkeydown = checkKey;
function checkKey(e) {
e = e || window.event;
if (e.keyCode == '39') {
    // right arrow
 var myAudio = document.getElementById("lionroar"); 
myAudio.play();
}
else if (e.keyCode == '37') {
    // left arrow
  var myAudio = document.getElementById("lionroar"); 
myAudio.pause();
}
}

I’ve added an element with this in the inner html

<audio controls="controls" height="50" id="lionroar" preload="auto" width="300">
<source src="cMajor.mp3" type="audio/mpeg">
</audio>

Chords Demo.hype.zip (1.3 MB)


(Mark Hunte) #7

Try

<audio controls="controls" height="50" id="lionroar" preload="auto" width="300">
<source src="${resourcesFolderName}/cMajor.mp3" type="audio/mpeg">
</audio>

:smile:


#8

Mark is right on the button there! :smile:

But, just as an FYI I’d like to point out a way to ‘clean up’ your code. Best practices for Javascript is to not repeat yourself. (DRY) I know, I know, I’m being pedantic but it does irk me somewhat! :smile:

document.onkeydown = function checkKey(e) {

var text = document.getElementById("text");
e = e || window.event;
	
if (e.keyCode == '39') {
	    
    // right arrow
    text.innerHTML = "Right Arrow";
	
}

else if (e.keyCode == '37') {
	
    // left arrow
    text.innerHTML = "Left Arrow";
	
    }
} 

Notice I didn’t use audio just text to make it easier :wink:

NOTE* This is only if you wanted to keep best practices and understand a little more about keeping Javascript DRY and by no means contributes to helping you solve your dilemma in any way :smile: take or leave it! I won’t be offended.

Or tell me to :no_mouth:

D


(Matt) #9

Is there some way to automatically set focus on the iframe or in other words automatically make the iframe the active window?


(Mark Hunte) #10

Not at my mac at mo. But try

element.focus();


(Mark Hunte) #11

This is what I meant. Which works really well.

We target the audio in the iFrame by using:

theWidget.children[0].contentDocument.getElementById("lionroar"); 

Left/right arrows would normally activate the play/pause if the Main window is in focus only.

But we simply put inside the iFrame widget, similar code that we use in the hype playPause() function,.
So if the iFrame gains focus ( like when the user clicks into it ) the play/paues will work as normal

<script type="text/javascript"> 

document.onkeydown = checkKey;
function checkKey(e) {
 console.log("checkKey");
 
 
 
 var myAudio =  document.getElementById("lionroar");

e = e || window.event;


if (e.keyCode == '39') {
    // right arrow
  
myAudio.play();
}
else if (e.keyCode == '37') {
    // left arrow
   
 myAudio.pause();
}
}
</script>

playPauseByKeysDetectIFrame-1.hypetemplate.zip (136.0 KB)


(Matt) #12

@MarkHunte thanks so much for this. It is really helpful!

I also have a similar question along the same lines that I cannot figure out:

I also have an iFrame with other interactive elements (not audio) that I need to have automatically set as the active window (“in focus”) when the scene loads. The entire Hype document is also in an iframe so I have an iframe within an iFrame.

Is there a solution related to this?

Thank you!


(Mark Hunte) #13

Did you look at the focus() command


(Mark Hunte) #14

Are you able to post the doc…


(Matt) #15

Here you go.
When the iframe is the active window you’ll be able to press computer keys to play notes.

aqwertyonExample.hype.zip (12.7 KB)


(Mark Hunte) #16

Hmm,

Whats the reason for the second iframe?. It is not needed as far as I can see.

You can set a specific source url in the inspector

Which means less messing about in the code.

Which would then become

  var aqwertyon = hypeDocument.getElementById('aqwertyon').children[0];
   
         aqwertyon.focus();

Also I you should not be setting a var name window

window is reserved.

You are in effect redefining the window object which will cause you no end of trouble.

aqwertyonExample.hype 2.zip (11.8 KB)


Update (wanted to double check this would work for this before I posted.)

In most cases I will always use a a Rectangle object and edit it’s innerHTML rather than a HTML Widget. and place an iFrame in this case within it.

The Rectangle does not carry all the baggage that the widget does in terms of a window object inside the parent window. ( at least thats how I see it).

This means that in effect the hypdocument will see the iframe within it’s own context. Therefore even though we have an iframe ( could even be a form or a TextArea) we can directly access the iframe’s properties.

So if we edit the Rectangle’s innHTML and we give the iFrame the id innerFrame

<iframe width="960px" height="560px" frameborder="0" id="innerFrame" src="http://nyumusedlab.github.io/aqwertyon/?session=29fa8&amp;video=&amp;scale=major&amp;sound=koto&amp;root=60&amp;volume=0.582&amp;show-takes=false&amp;show-video=false&amp;show-keyboard=true&amp;qwerty=false&amp;layout=1-3-5-8&amp;" <="" iframe=""></iframe>

we can then use the normal hype syntax

var aqwertyon = hypeDocument.getElementById('innerFrame')

ta da, no more messing about in this case.

aqwertyonExampleRect.hype.zip (12.9 KB)


(Mark Hunte) #17

I have updated the answer above…


(Matt) #18

Wow! It works perfectly!

Thank you so much for all of your help! :smile: