You are previewing HTML5 Canvas.

HTML5 Canvas

Cover of HTML5 Canvas by Steve Fulton... Published by O'Reilly Media, Inc.
  1. HTML5 Canvas
    1. SPECIAL OFFER: Upgrade this ebook with O’Reilly
    2. A Note Regarding Supplemental Files
    3. Preface
      1. Running the Examples in the Book
      2. What You Need to Know
      3. How This Book Is Organized
      4. Conventions Used in This Book
      5. Using Code Examples
      6. We’d Like to Hear from You
      7. Safari® Books Online
      8. Acknowledgments
    4. 1. Introduction to HTML5 Canvas
      1. The Basic HTML Page
      2. Basic HTML We Will Use in This Book
      3. The Document Object Model (DOM) and Canvas
      4. JavaScript and Canvas
      5. HTML5 Canvas “Hello World!”
      6. Debugging with Console.log
      7. The 2D Context and the Current State
      8. The HTML5 Canvas Object
      9. Another Example: Guess The Letter
      10. What’s Next
    5. 2. Drawing on the Canvas
      1. The Basic File Setup for This Chapter
      2. The Basic Rectangle Shape
      3. The Canvas State
      4. Using Paths to Create Lines
      5. Advanced Path Methods
      6. Compositing on the Canvas
      7. Simple Canvas Transformations
      8. Filling Objects with Colors and Gradients
      9. Filling Shapes with Patterns
      10. Creating Shadows on Canvas Shapes
      11. What’s Next
    6. 3. The HTML5 Canvas Text API
      1. Displaying Basic Text
      2. Setting the Text Font
      3. Text and the Canvas Context
      4. Text with Gradients and Patterns
      5. Width, Height, Scale, and toDataURL() Revisited
      6. Final Version of Text Arranger
      7. What’s Next
    7. 4. Images on the Canvas
      1. The Basic File Setup for This Chapter
      2. Image Basics
      3. Simple Cell-Based Sprite Animation
      4. Advanced Cell-Based Animation
      5. Applying Rotation Transformations to an Image
      6. Creating a Grid of Tiles
      7. Zooming and Panning an Image
      8. Pixel Manipulation
      9. Copying from One Canvas to Another
      10. What’s Next
    8. 5. Math, Physics, and Animation
      1. Moving in a Straight Line
      2. Bouncing Off Walls
      3. Curve and Circular Movement
      4. Simple Gravity, Elasticity, and Friction
      5. Easing
      6. What’s Next?
    9. 6. Mixing HTML5 Video and Canvas
      1. HTML5 Video Support
      2. Converting Video Formats
      3. Basic HTML5 Video Implementation
      4. Preloading Video in JavaScript
      5. Video and the Canvas
      6. Video on the Canvas Examples
      7. Animation Revisited: Moving Videos
      8. What’s Next?
    10. 7. Working with Audio
      1. The Basic <audio> Tag
      2. Audio Formats
      3. Audio Tag Properties, Functions, and Events
      4. Playing a Sound with No Audio Tag
      5. Creating a Canvas Audio Player
      6. Case Study in Audio: Space Raiders Game
      7. What’s Next
    11. 8. Canvas Game Essentials
      1. Why Games in HTML5?
      2. Our Basic Game HTML5 File
      3. Our Game’s Design
      4. Game Graphics: Drawing with Paths
      5. Animating on the Canvas
      6. Applying Transformations to Game Graphics
      7. Game Graphic Transformations
      8. Game Object Physics and Animation
      9. A Basic Game Framework
      10. Putting It All Together
      11. The player Object
      12. Geo Blaster Game Algorithms
      13. The Geo Blaster Basic Full Source
      14. Rock Object Prototype
      15. What’s Next
    12. 9. Combining Bitmaps and Sound
      1. Geo Blaster Extended
      2. Creating a Dynamic Tile Sheet at Runtime
      3. A Simple Tile-Based Game
      4. What’s Next
    13. 10. Mobilizing Games with PhoneGap
      1. Going Mobile!
      2. Creating the iOS Application with PhoneGap
      3. Beyond the Canvas
      4. What’s Next
    14. 11. Further Explorations
      1. 3D with WebGL
      2. Multiplayer Applications with ElectroServer 5
      3. Conclusion
    15. Index
    16. About the Authors
    17. Colophon
    18. SPECIAL OFFER: Upgrade this ebook with O’Reilly
O'Reilly logo

Playing a Sound with No Audio Tag

Now that we have a sound playing in an HTML5 page and we are tracking the properties of the audio element on the canvas, it is time to step up their integration. The next step is to do away with the <audio> tag embedded in the HTML page.

If you recall from Chapter 6, we created a video element dynamically in the HTML page and then used the canPlayType() method of the HTMLVideoElement object to figure out what video file type to load for a particular browser. We will do something very similar for audio.

Dynamically Creating an Audio Element in JavaScript

The first step to dynamically creating audio elements is to create a global variable named audioElement. This variable will hold an instance of HTMLAudioElement that we will use in our canvas application. Recall that audio elements in an HTML page are instances of the HTMLAudioElement DOM object. We refer to them as audio objects when embedded in an HTML page, and as instances of HTMLAudioElement when created dynamically in JavaScript. However, they are essentially the same.

Note

Don’t fret if you don’t like using global variables. By the end of this chapter, we will show you a way to make these variables local to your canvas application.

Next, we create our event handler for the window load event named eventWindowLoaded(). Inside that function, we call the createElement() function of the DOM document object, passing the value audio as the type of element to create. This will dynamically create an audio object and put it into the DOM. By placing that object in the audioElement variable, we can then dynamically place it onto the HTML page with a call to the appendChild() method of the document.body DOM object:

window.addEventListener('load', eventWindowLoaded, false);
var audioElement;
function eventWindowLoaded() {
   audioElement = document.createElement("audio");
   document.body.appendChild(audioElement);

However, just having a dynamically created audio element is not enough. We also need to set the src attribute of the HTMLAudioElement object represented by audioElement to a valid audio file to load and play. But the problem is that we don’t yet know what type of audio file the current browser supports. We will get that information from a function we will create named supportedAudioFormat(). We will define this function so that it returns a string value representing the extension of the file type we want to load. When we have that extension, we concatenate it with the name of the sound we want to load, and set the src with a call to the setAttribute() method of the HTMLAudioElement object:

var audioType = supportedAudioFormat(audioElement);

If a valid extension from supportedAudioFormat() is not returned, something has gone wrong and we need to halt execution. To handle this condition in a simple way we create an alert() message and then return from the function, effectively halting execution. While this is not a very robust form of error handling, it will work for the sake of this example:

if (audioType == "") {
   alert("no audio support");
   return;
}
audioElement.setAttribute("src", "song1." + audioType);

Finally, like we did with video, we will listen for the canplaythrough event of audioElement so that we know when the sound is ready to play:

audioElement.addEventListener("canplaythrough",audioLoaded,false);

Finding the Supported Audio Format

Before the code in the previous section will work, we need to define the supportedAudioFormat() function. Since we are adding audio objects dynamically to the HTML page, we do not have a way to define multiple <source> tags like we can in HTML. Instead, we are going to use the canPlayType() method of the audio object to tell us which type of audio file to load. We already introduced you to the canPlayType() method in Chapter 6, but to refresh your memory, canPlayType() takes a single parameter—a MIME type. It returns a text string of maybe, probably, or “” (nothing). We are going to use these values to figure out which media type to load and play. Just like in Chapter 6, and for the sake of this exercise, we are going to assume that both maybe and probably equate to yes. If we encounter either result with any of our three MIME types (audio/ogg, audio/wav, audio/mp3), we will return the extension associated with that MIME type so the sound file can be loaded.

Note

The next function is essentially the same as the one we created in Chapter 6 to handle video formats. The obvious changes here are with the MIME types for audio.

In the function below, audio represents the instance of HTMLAudioElement that we will test. The returnExtension variable represents that valid extension for the first MIME type found that has the value of maybe or probably returned:

function supportedAudioFormat(audio) {
   var returnExtension = "";
   if (audio.canPlayType("audio/ogg") =="probably" || 
       audio.canPlayType("audio/ogg") == "maybe") {
         returnExtension = "ogg";   } else if(audio.canPlayType("audio/wav") =="probably" || 
       audio.canPlayType("audio/wav") == "maybe") {
         returnExtension = "wav";
   } else if(audio.canPlayType("audio/mp3") == "probably" || 
       audio.canPlayType("audio/mp3") == "maybe") {
         returnExtension = "mp3";
   }

   return returnExtension;

}

Notice that we do not check for a condition when no valid audio format is found and the return value is “”. If that is the case, the code that has called this function might need to be written in a way to catch that condition and alter the program execution. We did that with the test of the return value and the alert() message, which we described in the previous section.

Note

If you want to test the error condition with no valid return value from this function, simply add an extra character to the MIME type (e.g., audio/oggx) to make sure an empty string is always returned.

Alternatively, you can use Modernizr to test for audio support. If you have included the Modernizr JavaScript library in your HTML page (as we have done in every application we have written thus far), you can access the static values of Modernizr.audio.ogg, Modernizr.audio.wav, and Modernizr.audio.mp3 to test to see whether those types are valid. These are not Booleans—they evaluate to the same probably, maybe, and “” values that we get from a call to canPlayType(). If you are comfortable using Modernizr for all your tests, you can replace the test in the code with tests of these Modernizr static values.

Playing the Sound

Finally, we get to the point where we can play a sound inside our canvasApp() function. Since we preloaded the sound originally outside the context of this function into a variable with a global scope, we just need to call the play() function audioElement to start playing the sound:

audioElement.play();

Figure 7-4 shows what this canvas application will look like when executed in an HTML5-compliant web browser (notice that we have left the display of the audio properties in this application).

Sound loaded and played “on” the canvas

Figure 7-4. Sound loaded and played “on” the canvas

Look Ma, No Tag!

Now, check out the full application in Example 7-4. Notice that there is no <audio> tag defined in the HTML, but the sound still plays. This is our first step toward integrating HTMLAudioElement objects with HTML5 Canvas.

Example 7-4. Playing a sound with no tag

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CH7EX4: Playing A Sound With No Tag</title>
<script src="modernizr-1.6.min.js"></script>
<script type="text/javascript">
window.addEventListener('load', eventWindowLoaded, false);
var audioElement;
function eventWindowLoaded() {

   audioElement = document.createElement("audio");
   document.body.appendChild(audioElement);
   var audioType = supportedAudioFormat(audioElement);
   if (audioType == "") {
      alert("no audio support");
      return;
   }
   audioElement.setAttribute("src", "song1." + audioType);
   audioElement.addEventListener("canplaythrough",audioLoaded,false);

}

function supportedAudioFormat(audio) {
   var returnExtension = "";
   if (audio.canPlayType("audio/ogg") =="probably" || 
       audio.canPlayType("audio/ogg") == "maybe") {
         returnExtension = "ogg";
   } else if(audio.canPlayType("audio/wav") =="probably" || 
       audio.canPlayType("audio/wav") == "maybe") {
         returnExtension = "wav";
   } else if(audio.canPlayType("audio/mp3") == "probably" || 
       audio.canPlayType("audio/mp3") == "maybe") {
         returnExtension = "mp3";
   }

   return returnExtension;

}

function canvasSupport () {
     return Modernizr.canvas;
}


function audioLoaded(event) {

   canvasApp();

}

function canvasApp() {

  if (!canvasSupport()) {
          return;
        }

  function  drawScreen () {

      //Background
      context.fillStyle = '#ffffaa';
      context.fillRect(0, 0, theCanvas.width, theCanvas.height);

      //Box
      context.strokeStyle = '#000000';
      context.strokeRect(5,  5, theCanvas.width−10, theCanvas.height−10);

      // Text
      context.fillStyle = "#000000";
      context.fillText  ("Duration:" + audioElement.duration,  20 ,20);
      context.fillText  ("Current time:" + audioElement.currentTime,  20 ,40);
      context.fillText  ("Loop: " + audioElement.loop,  20 ,60);
      context.fillText  ("Autoplay: " +audioElement.autoplay,  20 ,80);
      context.fillText  ("Muted: " + audioElement.muted,  20 ,100);
      context.fillText  ("Controls: " + audioElement.controls,  20 ,120);
      context.fillText  ("Volume: " + audioElement.volume,  20 ,140);
      context.fillText  ("Paused: " + audioElement.paused,  20 ,160);
      context.fillText  ("Ended: " + audioElement.ended,  20 ,180);
      context.fillText  ("Source: " + audioElement.currentSrc,  20 ,200);
      context.fillText  ("Can Play OGG: " + audioElement.canPlayType("audio/ogg"),  
                        20 ,220);
      context.fillText  ("Can Play WAV: " + audioElement.canPlayType("audio/wav"),  
                        20 ,240);
      context.fillText  ("Can Play MP3: " + audioElement.canPlayType("audio/mp3"),  
                        20 ,260);

   }

   var theCanvas = document.getElementById("canvasOne");
   var context = theCanvas.getContext("2d");
   audioElement.play()

   setInterval(drawScreen, 33);

}

</script>

</head>
<body>
<div style="position: absolute; top: 50px; left: 50px;">

<canvas id="canvasOne" width="500" height="300">
 Your browser does not support HTML5 Canvas.
</canvas>
</div>
</body>
</html>

The best content for your career. Discover unlimited learning on demand for around $1/day.