Using HTML5 video with canvas
You’ve already learned a lot about the <video>
element in my previous article “What I’ve Learned From Working With HTML5 Video Over A Month”, but did you know that the <video>
and <canvas>
elements would be a great choice to use together? In fact, the two elements are absolutely wondrous when you combine them! I’m going to show you a handy demo using these two elements, which I hope will prompt cool future projects from you. Firstly, place the <video>
and <canvas>
elements in your HTML. Give your dimensions(width, height) to <canvas>
according to your video. And of course, hide your video with the hidden attribute or “display: none” styling. Because
<canvas>
will do the trick for you ;) Let’s go through one by one.
View
1 2
<canvas width="1280" height="720"></canvas> <video src="foo.mp4" preload="auto" autoplay playsinline webkit-playsinline muted hidden></video>
We’re hiding the video element because we just want
<canvas>
to show the video, not<video>
element itself.
Declarations
Let’s declare the variables that will be used.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// These our <canvas> and <video> elements that will be used later. const canvas = document.querySelector('canvas') const video = document.querySelector('video') // fps means frame per second. It’s important according to the video’s // frame. You may want to use it as 24, or 30, or 60. It will be used // for the intervals millisecond value. const fps = 60 // width and height are the dimensions in pixels of the video. They // will be given to the canvas element. If you do not specify them, // <canvas> will take 300 for width and 150 for height as default // which may break your view. const width = 1280 const height = 720 // I will use canvasInterval variable to set and clear an interval to // make <canvas> follow and unfollow the <video> element. const canvasInterval = null
Logic
Here is the magical part, with the whole code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
const canvas = document.querySelector('canvas'); const video = document.querySelector('video'); const fps = 60; const width = 1280; const height = 720; const canvasInterval = null; drawImage() { canvas.getContext('2d', { alpha: false }).drawImage(video, 0, 0, width, height); } canvasInterval = window.setInterval(() => { drawImage(video); }, 1000 / fps); video.onpause = function() { clearInterval(canvasInterval); }; video.onended = function() { clearInterval(canvasInterval); }; video.onplay = function() { clearInterval(canvasInterval); canvasInterval = window.setInterval(() => { drawImage(video); }, 1000 / fps); };
drawImage()
method draws the video onto the canvas. video.onpause()
, video.onended()
, and video.onplay()
methods are related to the performance issue. When the video paused or ended, we do not need to draw <video>
onto the<canvas>
, because you know, the frame is not changing after paused or ended. And when the <video>
starts playing/resuming, <canvas>
should start/resume drawing the <video>
onto <canvas>
as well.