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

Easing

Easing is a technique used in animation to make an object smoothly enter or leave a location. The idea of easing is that instead of uniformly applying movement to every frame of animation, you instead increase (easing in) or decrease (easing out) the number of pixels you move on each frame. The result is that movement appears to be more realistic and smooth. There are many different ways to create easing animations. We will concentrate on two simple examples that will help pave the way for you to further explore the subject on your own.

Easing Out (Landing the Ship)

The process of easing out refers to easing at the end of an animation: an object moving from one point to another, starting out fast, and slowing down as it reaches the second point. To illustrate the concept, we will use the example of a spaceship landing. A spaceship starts out very fast, applies negative thrust to slow down, and, by the time it reaches the ground, is moving slowly enough to land without incident. If you’ve ever played the video game Lunar Lander, you will understand exactly the type of movement we are trying to accomplish.

To create this easing-out effect, we need to find two distinct points and then move an object between them, slowing down the object in linear fashion as it nears the second point. To achieve this effect, we first calculate the distance between the points. Next, we select a percentage value (easeValue) that we will use to move the object across that distance on each frame. As the distance gets shorter, the amount we move gets shorter as well. This gives the object the appearance of traveling slower and slower as it moves from the starting point to the ending point, as illustrated in Figure 5-21. We have drawn the points to show the easing values as the ship nears the bottom of the screen. Notice that the points get closer and closer until there is almost no distance between them.

Spaceship landing (easing out)

Figure 5-21. Spaceship landing (easing out)

Figure 5-21 displays the results of CH5EX18.html. Now, let’s look at how this example works in detail. First, we will load in the ship.png image the same way we have loaded images previously in this chapter:

var shipImage;
function eventWindowLoaded() {
   shipImage = new Image();
   shipImage.src = "ship.png"
   shipImage.onload = eventAssetsLoaded;
}

function eventAssetsLoaded() {

   canvasApp();
}

Then in canvasApp(), we create a variable named easeValue, which represents the percentage to move the ship across the remaining distance between the two points. In our example, it is 5% (.05):

var easeValue = .05;

Next, we create our two points. The first point, p1, is close to the middle of the canvas on the y-axis, and just above the top (-20) on the x-axis. The final point, p2, is in the same place on the x-axis, but near the bottom of the canvas (470) on the y-axis:

var p1 = {x:240,y:-20};
var p2 = {x:240,y:470};

Finally, we create a dynamic object for the ship that holds these values:

var ship = {x:p1.x, y:p1.y, endx: p2.x, endy:p2.y, velocityx:0, velocityy:0};

In drawScreen(), on every frame, we first find out the distance between the ship and the endpoint by subtracting the current x and y values for the ship from the endpoint x and y values. The distance will get shorter on each call to drawScreen() as the ship moves farther away from p1 and gets closer to p2. We do this for both x and y even though, in our example, only the y value will change as the spaceship gets closer to p2:

var dx = ship.endx - ship.x;
var dy = ship.endy - ship.y;

Once we have the distances, we multiply those values by easeValue to get the x and y velocities for the ship on this call to drawScreen():

ship.velocityx = dx * easeValue;
ship.velocityy = dy * easeValue;

Finally, we apply those values and draw the spaceship to the canvas:

ship.x += ship.velocityx;
ship.y += ship.velocityy;
context.drawImage(shipImage,ship.x,ship.y);

You can test this example by executing CH5EX18.html from the code distribution in your web browser, or by typing in the full code listing shown in Example 5-18.

Example 5-18. Easing out (landing the ship)

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CH5EX18:  Easing Out (Landing The Ship)</title>
<script src="modernizr-1.6.min.js"></script>
<script type="text/javascript">
window.addEventListener('load', eventWindowLoaded, false);
var shipImage;
function eventWindowLoaded() {
   shipImage = new Image();
   shipImage.src = "ship.png"
   shipImage.onload = eventAssetsLoaded;
}

function eventAssetsLoaded() {

   canvasApp();
}

function canvasSupport () {
     return Modernizr.canvas;
}

function canvasApp() {

   if (!canvasSupport()) {
           return;
}

  var pointImage = new Image();
  pointImage.src = "pointwhite.png";
  function  drawScreen () {

      context.fillStyle = '#000000';
      context.fillRect(0, 0, theCanvas.width, theCanvas.height);
      //Box
      context.strokeStyle = '#ffffff';
      context.strokeRect(1,  1, theCanvas.width-2, theCanvas.height-2);
      var dx = ship.endx - ship.x;
      var dy = ship.endy - ship.y;

      ship.velocityx = dx * easeValue;
      ship.velocityy = dy * easeValue;

      ship.x += ship.velocityx;
      ship.y += ship.velocityy;

      //Draw points to illustrate path

      points.push({x:ship.x,y:ship.y});

      for (var i = 0; i< points.length; i++) {
         context.drawImage(pointImage, points[i].x+shipImage.width/2, points[i].y,1,1);
      }

      context.drawImage(shipImage,ship.x,ship.y);

   }   var easeValue = .05;
   var p1 = {x:240,y:-20};
   var p2 = {x:240,y:470};

   var ship = {x:p1.x, y:p1.y, endx: p2.x, endy:p2.y, velocityx:0, velocityy:0};
   var points = new Array();

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

   setInterval(drawScreen, 33);

}

</script>

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

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

Note

We are showing the points in this example but because the background is black, we load in a white bitmap point image named pointwhite.png instead of the all-black image, point.png.

Easing In (Taking Off)

Easing in is the opposite of easing out. When an animation eases in, it starts slowly and then gets faster and faster. If you have ever seen a video of a space shuttle taking off, you will understand this much better. The thrust builds up as the craft moves slowly, and then gets faster and faster as it moves through the sky. We are going to use this “taking off” example as a way to develop code for an easing-in animation on HTML5 Canvas.

In canvasApp(), we start our code much the same way as in the last example—by creating a variable named easeValue:

var easeValue = .05;

However, for easing in, instead of this being a percentage of the remaining distance between two points, it is simply a constant value added to the velocity of the ship on each frame. Figure 5-22 shows what this would look like. We have added the points again to illustrate how the animation speeds up as the ship takes off.

Ship taking off (easing in)

Figure 5-22. Ship taking off (easing in)

First, we set the beginning position of the ship (p1) to the bottom center of the canvas. Then, we set the beginning speed of the ship very low (.5 pixels per frame), and set the angle to 270 (straight up the canvas). We then calculate the x and y velocity values for the ship:

var p1 = {x:240,y:470};
var tempSpeed = .5;
var tempAngle = 270 ;
var tempRadians = tempAngle * Math.PI/ 180;
var tempvelocityx = Math.cos(tempRadians) * tempSpeed;
var tempvelocityy  = Math.sin(tempRadians) * tempSpeed;

var ship = {x:p1.x, y:p1.y, velocityx:tempvelocityx, velocityy:tempvelocityy};

In drawScreen(), instead of finding the distance between two points, we add the easeValue to the x and y velocities on each frame, and then apply it to the ship x and y values before drawing it to the canvas. This creates a linear increase in speed, resulting in the easing-in effect we want to see:

ship.velocityx = ship.velocityx + ( ship.velocityx*easeValue);
ship.velocityy = ship.velocityy + ( ship.velocityy*easeValue);

ship.x += ship.velocityx;
ship.y += ship.velocityy;

context.drawImage(shipImage,ship.x,ship.y);

You can see this example by executing CH5EX19.html from the code distribution, or by typing in the code listing shown in Example 5-19.

Example 5-19. Easing in (taking off)

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CH5EX19: Taking Off (Fake Ease In)</title>
<script src="modernizr-1.6.min.js"></script>
<script type="text/javascript">
window.addEventListener('load', eventWindowLoaded, false);
var shipImage;
function eventWindowLoaded() {
   shipImage = new Image();
   shipImage.src = "ship.png"
   shipImage.onload = eventAssetsLoaded;
}

function eventAssetsLoaded() {

   canvasApp();
}

function canvasSupport () {
    return Modernizr.canvas;
}

function canvasApp() {

    if (!canvasSupport()) {
          return;
        }

  var pointImage = new Image();
  pointImage.src = "pointwhite.png";
  function  drawScreen () {

      context.fillStyle = '#000000';
      context.fillRect(0, 0, theCanvas.width, theCanvas.height);
      //Box
      context.strokeStyle = '#ffffff';
      context.strokeRect(1,  1, theCanvas.width-2, theCanvas.height-2);

      ship.velocityx = ship.velocityx + ( ship.velocityx*easeValue);
      ship.velocityy = ship.velocityy + ( ship.velocityy*easeValue);

      ship.x += ship.velocityx;
      ship.y += ship.velocityy;

      //Draw points to illustrate path

      points.push({x:ship.x,y:ship.y});

      for (var i = 0; i< points.length; i++) {
         context.drawImage(pointImage, points[i].x+shipImage.width/2, points[i].y,1,1);
      }

      context.drawImage(shipImage,ship.x,ship.y);

   }

   var easeValue = .05;
   var p1 = {x:240,y:470};
   var tempX;
   var tempY;
   var tempSpeed = .5;
   var tempAngle = 270 ;
   var tempRadians = tempAngle * Math.PI/ 180;
   var tempvelocityx = Math.cos(tempRadians) * tempSpeed;
   var tempvelocityy  = Math.sin(tempRadians) * tempSpeed;

   var ship = {x:p1.x, y:p1.y, velocityx:tempvelocityx, velocityy:tempvelocityy};
   var points = new Array();

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

   setInterval(drawScreen, 33);

}

</script>

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

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

Note

For more information on easing, check out Robert Penner’s easing equations: http://www.robertpenner.com/easing/. These equations have been implemented in jQuery for JavaScript at http://plugins.jquery.com/files/jquery.animation.easing.js.txt.

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