demosthenes.info

I’m Dudley Storey, the author of Pro CSS3 Animation. This is my blog, where I talk about web design and development with , and . To receive more information, including news, updates, and tips, you should follow me on Twitter or add me on Google+.

web developer guide

my books

Book cover of Pro CSS3 AnimationPro CSS3 Animation, Apress, 2013

my projects

A Sass color keyword system for designers. Replaces CSS defaults with improved hues and more memorable, relevant color names.

CSSslidy: an auto-generated #RWD image slider. 3.8K of JS, no JQuery. Drop in images, add a line of CSS. Done.

tipster.ioAutomatically provides local tipping customs and percentages for services anywhere.

Electronica Site Navigation, Part 2: HTML5 Audio Events

html / multimedia

Estimated reading time: 2 minutes, 30 seconds

Inspired by soundboard sites such as iDaft, I wanted to add audio events to the HTML5 animated menu bar I made in part one of this series. As a rule, I feel that web sites should only “speak when spoken to”, i.e. the majority of web pages should not play audio by default, and leave initiation of playback up to the user. Auto-playing background music on sites makes me angry. I was willing to craft an exception for this example for two reasons: (a) it’s for a music site, in which audio could be reasonably expected to play a part and (b) the code is a proof-of-concept, not an actual site.

Sans Flash or other plugin, we can add sound to a webpage in two ways: either instancing the audio solely through JavaScript, or by embedding the sound on the page with the <audio> tag. In this case, we need to add four sounds: one for each link, with different codecs to cover the current browser incompatibles. Anywhere in the body, I’ll place the following:

<audio preload="auto" id=harder">
<source src="assets/audio/harder.mp3">
<source src="assets/audio/harder.ogg">
</audio>
<audio preload="auto" id=better">
<source src="assets/audio/better.mp3">
<source src="assets/audio/better.ogg">
</audio>
<audio preload="auto" id=faster">
<source src="assets/audio/faster.mp3">
<source src="assets/audio/faster.mp3">
</audio>
<audio preload="auto" id=stronger">
<source src="assets/audio/stronger.mp3">
<source src="assets/audio/stronger.ogg">
</audio>

Note that we have effectively hidden the sounds on the page by not adding a controls attribute.

I’ll also need to add an id to each link, in order to be able to address them specifically with JavaScript:

<nav id=equalizer>
<a href="#" style="left: 20px;" id=beats><span>Beats</span></a>
<a href="#" style="left: 170px;" id=samples><span>Samples</span></a>
<a href="#" style="left: 320px;" id=loops><span>Loops</span></a>
<a href="#" style="left: 470px;" id=rhythms><span>Rhythms</span></a>
</nav>

The next part is addressing each audio source and linking it to the mouseover state of each link. I’ll use JQuery to do so, just because it is a little easier to write. In the head section of the page, add:

<script>
$(document).ready(function() {
var harder = $("#harder")[0];
var better = $("#better")[0];
var faster = $("#faster")[0];
var stronger = $("#stronger")[0];
$("#equalizer a#beats")
.mouseenter(function() {
harder.play();
});
$("#equalizer a#samples")
.mouseenter(function() {
better.play();
});
$("#equalizer a#loops")
.mouseenter(function() {
faster.play();
});
$("#equalizer a#rhythms")
.mouseenter(function() {
stronger.play();
});
});
</script>

This works, with a few caveats.  Critically, the code is lengthy and heavily repetitious. I’ll clean it up by adding a class to each link that signifies the sound I want to associate with it. The value of that class will match that of the id on the audio tags, so I can cross-reference them easily. So the nav is altered to:

<nav id=equalizer>
<a href="#" style="left: 20px;" class="harder"><span>Beats</span></a>
<a href="#" style="left: 170px;" class="better"><span>Samples</span></a>
<a href="#" style="left: 320px;" class="faster"><span>Loops</span></a>
<a href="#" style="left: 470px;" class="stronger"><span>Rhythms</span></a>
</nav>

And the JavaScript becomes:

$(document).ready(function() {
$("#equalizer a")
.mouseenter(function() {
var link = $(this);
var ref = link.attr("class");
$("#"+ref)[0].play();
});
});

The JavaScript could be shortened down even further:

$("#equalizer a")
.mouseenter(function() {
$("#"+$(this).attr("class"))[0].play();
});

I could make a true graphic equalizer effect with the proposed Web Audio API, but support for that is limited to Firefox at the moment.

There are a few other issues with the menu, mostly to do with browser support for HTML5 audio: depending on the browser version you use, the sound from the first hover may come after a small delay, and the audio clips may not “step” on each other the way one might expect. I’ll address those problems in a future article.

comments powered by Disqus

This site helps millions of visitors while remaining ad-free. For less than the price of a cup of coffee, you can help pay for bandwidth and server costs while encouraging further articles.