- Chapter 9: Using Video with Canvas
- The Canvas Element
- The 2D API
- Taking a Screen Shot of an HTML5 Video
- Making a Copy of a Playing Video
- Playing the Video Copy in Greyscale
- Wrapping Up
Taking a Screen Shot of an HTML5 Video
Say, for example, that you want to allow users to take screen shots of your video as it’s playing and display them somewhere else, for example, on the web page next to the video. You can use a canvas element as the drawing surface in which to actually place the screen shot image.
Sound a bit complicated? Well, it’s not. You only need to use two of the -JavaScript API functions: fillRect()and one other that you’ll read about in a moment.
Before you take the screen shot, you must first set up the video and a button for taking the screen shot, as well as complete a few other initialisation tasks.
First up, set up the HTML for the video, button, and canvas elements:
<video controls> <source src=”elephants-dream-medium.mp4” type=”video/mp4”> <source src=”elephants-dream-medium.webm” type=”video/webm”> </video> <canvas></canvas> <button id=”snap”>Take screenshot</button>
Notice that there’s no width and height specified on the canvas element yet; that will be done via JavaScript later, so don’t worry! You’ll also add a function to the onclick event of the button element; again, this will happen a bit later on.
Now on to some JavaScript. Recall that you need to grab a handle to the 2D drawing context of the canvas element. You also need to get a handle to the video element because you’ll need that later:
var video = document.querySelector(‘video’); var canvas = document.querySelector(‘canvas’); var context = canvas.getContext(‘2d’); var w, h, ratio;
Some other variables are also defined for later use: for example, the w (width) and h (height), whose names make the data they’ll contain quite obvious.
In this example, you’ll create screen shots that are smaller than the video. This shows that it is possible to work with screen shots that have a different size than the original video.
It was mentioned earlier that the dimensions of the canvas element need to be defined should you want to override the default dimensions of 300 × 150, which you do here. Therefore, you need to work out the ratio of the video’s width to its height (hence the ratio variable defined in the previous code snippet). You also can only do this when the video is actually available for the browser to be able to check the dimensions of the video. So, you need to wait until the video’s dimensions are available. And how do you do this? By listening for the loadedmetadata API event that you may recall from Chapter 5:
video.addEventListener(‘loadedmetadata’, function() { ratio = video.videoWidth / video.videoHeight; w = video.videoWidth - 100; h = parseInt(w / ratio, 10); canvas.width = w; canvas.height = h; }, false);
When the loadedmetadata event is raised, the ratio of the video is calculated. The w variable is then set to be (arbitrarily) 100 less than the actual width of the video, and the h variable is set to whatever ratio the value in w is to the video’s ratio. The canvas element’s width and height are then set to the calculated values in w and h.
You then need to define the actual function that will take the screen shot and attach it to the button’s onclick event. But before you do so, let’s take a quick look at the other 2D API function that you’ll need here, drawImage().
The drawImage(image, x, y, w, h) function can take a number of parameters, but you’ll only use five of them in this example. As its name suggests, this function allows you to draw an image onto the canvas. The first parameter is the image to draw, and the next four are the same as in fillRect(): the X and Y coordinates of the drawn image’s top-left corner, and its width and height.
The image parameter can be one of the following HTML elements: img, -canvas, or video. Yes, the video element can be passed to this function, and it will automatically create an image from the current frame of the video in question and draw it on the canvas.
Next, you define the function snap() to take the actual screen shot and attach it to the button element:
<button id=”snap” onclick=”snap()”>Take screenshot</button> And snap() is defined as: function snap() { context.fillRect(0, 0, w, h); context.drawImage(video, 0, 0, w, h); }
Two lines are all that are required! The rectangle in the canvas that will be filled is defined first—in this case it’s the entire canvas element—and then you use drawImage() to draw the image from the video.
That’s all it takes to take a screen shot from the video. As the video is playing, you can keep clicking the “Take screenshot” button and a new screen shot of the video will be taken at whatever point it’s at (Figure 9.2).
Figure 9.2 The canvas element on the right (A) is empty to begin with until the “Take screenshot” button is clicked, which draws a still from the video as an image on the canvas (B).
Most of the coding effort involved setting up the video, button, and canvas elements, whereas the actual work only took two lines, which is the biggest advantage of canvas and is kinda cool.
You’ll expand on this example next by copying the entire video into the canvas element as it’s playing.