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

Zooming and Panning an Image

In this section, we will examine some methods to zoom and pan an image on the canvas. The image we are going to use is from a recent vacation to Central California. It is a large .jpg file, measuring 3648×2736. Obviously, this is far too large to view in a single canvas, so we will build a simple application allowing us to zoom and pan the image on our 500×500 canvas.

Figure 4-11 is a scaled-down version of this image.

A scaled-down version of the image we will zoom and pan

Figure 4-11. A scaled-down version of the image we will zoom and pan

Creating a Window for the Image

The first thing we are going to do is create a logical window, the size of the canvas, where our image will reside. We will use the following two variables to control the dimensions of this window:

var windowWidth = 500;
var windowHeight = 500;

We will also create two variables to define the current top-left corner for the window. When we move on to the panning examples, we will modify these values to redraw the image based on this location:

var windowX = 0;
var windowY = 0;

Drawing the Image Window

To draw the image window, we will simply modify the standard context.drawImage() function call using the values in the four variables we just defined:

context.drawImage(photo, windowX, windowY, windowWidth, windowHeight, 0, 0,
    windowWidth,windowHeight);

Let’s take a closer look at this for a refresher on how the drawImage() function operates. The values are passed in order:

photo

The image instance we are going to use as our source for painting onto the canvas

windowX

The top-left x location to start copying from the source image

windowY

The top-left y location to start copying from the source image

windowWidth

The width of the rectangle to start copying from the source image

windowHeight

The height of the rectangle to start copying from the source image

0

The top-left x destination location for the image on the canvas

0

The top-left y destination location for the image on the canvas

windowWidth

The width in pixels for the destination copy (this can be modified to scale the image)

windowHeight

The height in pixels for the destination copy (this can be modified to scale the image)

When we draw from the image to the canvas, we will be modifying the windowX and windowY values to create a panning effect. Example 4-11 demonstrates how to get the image onto the canvas with the window location set to 0,0. Figure 4-12 shows an example of the output for Example 4-11.

Example 4-11. Placing an image on the canvas in a logical window

var photo = new Image();
photo.addEventListener('load', eventPhotoLoaded , false);

photo.src = "butterfly.jpg";

var windowWidth = 500;
var windowHeight = 500;

var windowX = 0;
var windowY = 0;

function eventPhotoLoaded() {
   drawScreen()
}

function drawScreen(){
  context.drawImage(photo, windowX, windowY, windowWidth, windowHeight,
    0, 0, windowWidth,windowHeight);
}
An image in a small logical window

Figure 4-12. An image in a small logical window

Panning the Image

To pan the window across the image, we simply need to modify the windowX and windowY coordinates. In Example 4-12, we will modify the windowX coordinate inside a frame tick interval. During each loop iteration, we will increase the value of windowX by 10. We need to be careful not to go off the far right side of the image, so we will subtract the windowWidth from the image.width, and use the result as the maximum windowX position:

windowX+ = 10;
if (windowX>photo.width - windowWidth){
  windowX = photo.width - windowWidth;
}

Example 4-12 contains the changes necessary to perform this panning operation.

Example 4-12. Simple image panning

var photo = new Image();
photo.addEventListener('load', eventPhotoLoaded , false);

photo.src = "butterfly.jpg";

var windowWidth = 500;
var windowHeight = 500;

var windowX = 0;
var windowY = 0;

function eventPhotoLoaded() {
   startUp();
}

function drawScreen(){

   context.drawImage(photo, windowX, windowY, windowWidth, windowHeight,
       0,0,windowWidth,windowHeight);

   windowX += 10;
   if (windowX>photo.width - windowWidth){
       windowX = photo.width - windowWidth;
   }

}

function startUp(){

   setInterval(drawScreen, 100 );
}

When you test Example 4-12, you will see the window pan across the image and stop at the rightmost edge. Next, we will start to implement zooming into this simple example.

Zoom and Pan the Image

To zoom in or out of an image, we need to change the final width and height values of the drawImage() function. Let’s examine how we would zoom out to 50% of the original size of the image while panning at the same time. The drawImage() function will look like this:

context.drawImage(photo, windowX, windowY, windowWidth, windowHeight,
   0, 0, windowWidth*.5,windowHeight*.5);

Example 4-13 modifies Example 4-12 and adds in the 50% zoom.

Example 4-13. Pan an image with a preset zoom out

var photo = new Image();
photo.addEventListener('load', eventPhotoLoaded , false);

photo.src = "butterfly.jpg";
var windowWidth = 500;
var windowHeight = 500;

var windowX = 0;
var windowY = 0;

function eventPhotoLoaded() {
   startUp();
}

function drawScreen(){

   context.drawImage(photo, windowX, windowY, windowWidth, windowHeight,
       0,0,windowWidth*.5,windowHeight*.5);

   windowX += 10;
   if (windowX>photo.width - windowWidth){
       windowX = photo.width - windowWidth;
   }

}

function startUp(){

   setInterval(drawScreen, 100 );
}

When we test this example, we will see that when zoomed out, the image on the canvas is 50% of its original size. To zoom in, we simply change the scale factor from .5 to a number greater than 1:

context.drawImage(photo, windowX, windowY, windowWidth,windowHeight,
   0,0,windowWidth*2,windowHeight*2);

Example 4-14 changes this single line from Example 4-13 to zoom in rather than zoom out.

Example 4-14. Pan an image with a preset zoom amount

var photo = new Image();
photo.addEventListener('load', eventPhotoLoaded , false);

photo.src = "butterfly.jpg";

var windowWidth = 500;
var windowHeight = 500;

var windowX = 0;
var windowY = 0;


function eventPhotoLoaded() {
   startUp();
}

function drawScreen(){

   context.drawImage(photo, windowX, windowY, windowWidth, windowHeight,
       0,0,windowWidth*2,windowHeight*2);

   windowX += 10;
   if (windowX>photo.width - windowWidth){
       windowX = photo.width - windowWidth;
   }
}

function startUp(){

   setInterval(drawScreen, 100 );
}

Application: Controlled Pan and Zoom

Our final example for this section will be a simple application allowing the user to zoom and pan a photo.

The zoom scale

We are going to create a set of variables to handle the current zoom scale, the factor by which the zoom scale is increased or decreased, as well as the maximum and minimum zoom values:

var currentScale = .5;
var minScale = .2
var maxScale = 3;
var scaleIncrement = .1;

We will apply these values to the drawImage() function:

context.drawImage(photo, windowX, windowY, windowWidth, windowHeight,
    0,0,windowWidth*currentScale,windowHeight*currentScale);

Keyboard input

Now we need to create a keyboard listener function. The following function seems to work best in all browsers tested—it’s certainly not the only keyboard event listener, but it is tried and true throughout this book:

document.onkeydown = function(e){
   e = e?e:window.event;
}

Note

This function utilizes the ternary operator. If the statement before the ? is true, the statement following the ? is executed. If it is false, the statement after the : is executed. This is a shorthand version of the classic if/else construct.

We will add a switch/case statement, combining all the functions we have put into the previous zoom and pan examples, along with a new set of code for the y direction panning that we have not implemented before. It is very similar to the x direction panning: the left arrow key will pan the image to the left; the right arrow key will pan the image to the right:

case 38:
      //up
      windowY-=10;
      if (windowY<0){
         windowY = 0;
      }
      break;
case 40:
      //down
      windowY+=10;
      if (windowY>photo.height - windowHeight){
         windowY = photo.height - windowHeight;
      }
      break;
case 37:
      //left
      windowX-=10;
      if (windowX<0){
         windowX = 0;
      }
      break;
case 39:
       //right
      windowX+=10;
      if (windowX>photo.width - windowWidth){
         windowX = photo.width - windowWidth;
      }
      break;

We also need to add in two cases for the + and - keys to perform zoom in and zoom out actions:

case 109:
       //-
       currentScale-=scaleIncrement;
       if (currentScale<minScale){
          currentScale = minScale;
       }
       break;
case 107:
       //+
       currentScale+=scaleIncrement;
       if (currentScale>maxScale){
          currentScale = maxScale;
       }

When the user presses the + or - key, the currentScale variable is either incremented or decremented by the scaleIncrement value. If the new value of currentScale is greater than maxScale or lower than minScale, we set it to maxScale or minScale, respectively.

Example 4-15 puts this entire application together. It doesn’t take many lines of code to create the simple interactions.

Example 4-15. Image pan and zoom application

var photo = new Image();
photo.addEventListener('load', eventPhotoLoaded , false);

photo.src = "butterfly.jpg";

var windowWidth = 500;
var windowHeight = 500;

var windowX = 0;
var windowY = 0;
var currentScale = .5;
var minScale = .2
var maxScale = 3;
var scaleIncrement = .1;

function eventPhotoLoaded() {
   startUp();
}

function drawScreen(){

   //draw a background so we can see the Canvas edges
   context.fillStyle = "#ffffff";
   context.fillRect(0,0,500,500);

   context.drawImage(photo, windowX, windowY, windowWidth, windowHeight,
     0,0,windowWidth*currentScale,windowHeight*currentScale);

}

function startUp(){

   setInterval(drawScreen, 100 );
}

document.onkeydown = function(e){

   e = e?e:window.event;
   console.log(e.keyCode + "down");

   switch (e.keyCode){
      case 38:
            //up
            windowY-=10;
            if (windowY<0){
               windowY = 0;
            }
            break;
      case 40:
            //down
            windowY+=10;
            if (windowY>photo.height - windowHeight){
               windowY = photo.height - windowHeight;
            }
            break;
      case 37:
            //left
            windowX-=10;
            if (windowX<0){
               windowX = 0;
            }
            break;
      case 39:
            //right
            windowX+=10;
            if (windowX>photo.width - windowWidth){
               windowX = photo.width - windowWidth;
            }
            break;
      case 109:
            //-
            currentScale-=scaleIncrement;
            if (currentScale<minScale){
               currentScale = minScale;
            }
            break;
      case 107:
            //+
            currentScale+=scaleIncrement;
            if (currentScale>maxScale){
               currentScale = maxScale;
         }
   }

}

When testing Example 4-15, use the arrow keys to pan across the photo, and the + and - keys to zoom in and out.

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