Bing Maps and HTML5 Audio – Once more, with feeling!

I’ve already written articles demonstrating a couple of new HTML5 features and Bing Maps – notably, the <canvas> element and the geolocation API. In this post, I’ll have a look at one of the other new elements in the HTML5 specification, the <audio> tag.

Personally, I find webpages that play music in the background are right up there on the “annoying” list next to those that use the <blink> tag, or those riddled with popup banner adverts. However, there are some genuine use cases for audio in webpages:

  • Discrete use of subtle sound effects can provide positive feedback for user interfaces. For example, consider touch keyboard inputs that emulate the “clicking” noise of a typewriter to confirm when a key has been pressed.
  • Sound effects can also improve accessibility of a page, by providing audio cues for the elements of a user interface, in much the same way that a screenreader does.

I’m not an expert in UI design or in accessibility, so I’m not claiming that this article exhibits best practice in either of those areas, but at least I’d like to demonstrate what is technically possible using HTML5 <audio> and Bing Maps, by playing a simple sound effect when the mouse is placed over a polygon on the map.

Testing for Browser Audio Support

The HTML5 specification is still not fixed, and the level of support for HTML5 across different browsers is variable. At the time of writing, the most recent version of all major browsers support the <audio> tag itself, although the actual formats of audio file that can be played varies between browser. Rather frustratingly, there is no single file type supported across all browsers, as shown in the following table:

Format IE9 Firefox 3.6 /4 Opera 10.6 Chrome 10 Safari 3
Ogg Vorbis No Yes Yes Yes No
MP3 Yes No No No Yes
Wav Yes Yes Yes No Yes

(information aggregated from http://html5doctor.com/native-audio-in-the-browser/ and  http://thebrowsereview.com/html5/html5-audio-tag-and-format-support/)

Before using any of the new <audio> features, the first thing to do is therefore to check whether the user’s browser supports audio. This can be done in javascript by attempting to create a new audio element and calling the canPlayType function.

var supportsAudio = !!(document.createElement('audio').canPlayType);

This function will return a boolean result of true if the browser supports HTML5 audio, or false otherwise. If the browser does support audio, you can find out if a particular audio file format is supported by passing a parameter to canPlayType, representing the MIME type of an audio format. For example, to test whether the browser supports MP3 audio:

var supportsMP3 = (document.createElement('audio').canPlayType('audio/mpeg');

Note that, unlike the boolean response obtained when canPlayType is called with no parameters (which tests whether the browser implements audio at all), the response given when used to test whether a particular audio file type is supported is either “”, “maybe”, or “probably”.

Specifying a Source Audio File

Having determined the audio formats supported by the browser, you can then use a conditional statement to specify which source file should be used. For example:

var audio = document.createElement('audio');

// Create the source audio file element
var source = document.createElement('source');
// Test if the browser supports MPEG audio
if (audio.canPlayType('audio/mpeg') != "") {
source.type = 'audio/mpeg';
source.src = 'soundfile.mp3';
}
// Test if the browser supports OGG audio
else if (audio.canPlayType('audio/ogg; codecs="vorbis"') != "") {
source.type = 'audio/ogg';
source.src = 'soundfile.ogg';
}

audio.appendChild(source);

If Music Be the Food of Love, Play On…. (Or stop, as appropriate)

The final step is to attach handlers to the map to listen for particular events, and then set these handlers to start or stop the audio as appropriate. For this example, I’m going to attach a handler to the mouseover event of a polygon, causing the audio file to play while the user hovers their cursor over the shape in question:

var Handler = Microsoft.Maps.Events.addHandler(polygon, 'mouseover', function(e) {
audio.play();
});

And, when the user moves their mouse off the polygon, I want to stop the sound again. Note that the HTML5 audio standard doesn’t actually define a stop method, but rather a pause method to stop playback:

var Handler = Microsoft.Maps.Events.addHandler(polygon, 'mouseout', function(e) {
audio.pause();
});

Putting It All Together

A full code listing demonstrating the audio functionality is shown following. This example has been tested and confirmed to work in Firefox 4, Internet Explorer 9 and Chrome

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Bing Maps HTML5 Audio</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript" src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"></script>
<script type="text/javascript">

// Declare a shorthand alias for the Microsoft.Maps namespace
var MM = Microsoft.Maps;

function GetMap() {
// Create a basic map
var map = new MM.Map(document.getElementById("mapDiv"),
{ credentials: "YOUR BING MAPS KEY HERE",
center: new Microsoft.Maps.Location(54, -2),
mapTypeId: Microsoft.Maps.MapTypeId.birdseye,
zoom: 5
});

// Create a polygon
var polygon = new MM.Polygon([new MM.Location(50, -7),new MM.Location(52.5, 2),new MM.Location(59, -3),new MM.Location(57, -6),new MM.Location(50, -7)]);
// Add the polygon to the map
map.entities.push(polygon);

// Try to create an audio element
var audio = GetAudio('notify');
// If audio is supported
if (audio) {
// Play music when the mouse is over the polygon
var Handler = Microsoft.Maps.Events.addHandler(polygon, 'mouseover', function(e) {
audio.play();
});
// Stop audio when the mouse leaves the polygon
var MouseOutHandler = Microsoft.Maps.Events.addHandler(polygon, 'mouseout', function(e) {
audio.pause();
});
}
}

/* Tests for browser audio support, and specifies
* the appropriate source file extension depending
* on supported audio file types */
function GetAudio(filename) {
// Try creating an <audio> tag
var audio = document.createElement('audio');
// If the browser supports <audio>
if (audio.canPlayType) {
// Create the source audio file element
var source = document.createElement('source');
// Test if the browser supports MPEG audio
if (audio.canPlayType('audio/mpeg') != "") {
source.type = 'audio/mpeg';
source.src = filename + '.mp3';
}
// Test if the browser supports WAV audio
else if (audio.canPlayType('audio/wav') != "") {
source.type = 'audio/wav';
source.src = filename + '.wav';
}
// Test if the browser supports OGG audio
else if (audio.canPlayType('audio/ogg; codecs=vorbis') != "") {
source.type = 'audio/ogg; codecs=vorbis';
source.src = filename + '.ogg';
}
// Append the matching format file to the <audio> element
audio.appendChild(source);

return audio;
}
// If <audio> is not supported
else {
return null;
}
}
</script>
</head>
<body onload="GetMap();">
<div id='mapDiv' style="position:relative; width:600px; height:800px;"></div>
</body>
</html>

If you can imagine audio in a screenshot, then it probably looks a bit like this:

image

And you an see a live demo by going to: http://a3uk.com/clients/bingmaps/v7/html5audio/html5audio.htm

This entry was posted in Bing Maps and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s