学习如何绘制视频帧到一个Canvas元素,并促进各种效果
1. Video the star
Sites such as sailing-with-greenpeace.com make web video the central focal point to the experience. HTML5, and the ability to embed and play video natively inside the browser, makes this kind of design far more robust. The Greenpeace project utilises the <video> tag for intro background and archive clips, all stretched full width to provide an immersive experience.
2. The <video> tag
HTML5 video begins with the tag itself, defining attributes for how the player element appears or behaves. A set of <source> tags wrapped inside then point to each file path and the encoding types: WEBM, MP4 and OGG formats. In this example we will start from a video tag like so:
<video id="theVideo" autoplay loop> <source src="myVideo.webm" type=video/webm> <source src="myVideo.mp4" type=video/mp4> <source src="myVideo.ogg" type=video/ogg> </video>
3. Canvas and overlay wrapper
Our video tag from the last step is called ‘theVideo’, is set to be looped and will autoplay – this is useful for full-width/height backgrounds. This is also how we’ll use it here, although rather than maximise the video we’ll draw the video to a full-screen <canvas> element instead, placed above our video within a wrapper
<div> element: <div id="overlay" class="fullsize"> <canvas id="theCanvas" class="fullsize"></canvas> <video id="theVideo" autoplay loop> <source src="myVideo.webm" type=video/webm> <source src="myVideo.mp4" type=video/mp4> <source src="myVideo.ogg" type=video/ogg> </video> </div>
4. Force elements to be .fullsize
Moving to our CSS, we start our styling with the .fullsize class linked to the Canvas and wrapper elements. Both of these will occupy 100 per cent of the browser by setting dimensions to maximum percentage, while positioned absolute and all four edges forced to zero.
.fullsize { width: 100%; height: 100%; position: absolute; top: 0; bottom: 0; left: 0; right: 0; }
5. Add the patterned overlay
In this instance, our Canvas video background will be deliberately styled to appear pixelated by using a repeating transparent PNG grid pattern overlay. This is achieved via the full-screen overlay wrapper <div> and by setting its background to the simple pattern graphic. Here you can see the class with the background set to the image file itself or the base64 encode:
#overlay { background: url(grid.png) fixed repeat; background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAGklEQVQYGWNkgID/UBonRVABE06tSBLDWxEAcWcCDlgMZ/kAAAAASUVORK5CYII=') fixed repeat; }
6. Additional element styles
Now add a couple of classes for cosmetic tweaks. Lower the opacity of our Canvas very slightly to make the overlay more prominent. Secondly, we can either position our video box on the page to compare playback or hide it by setting display to none, shown commented here:
#theCanvas { opacity: 0.8; } #theVideo { position: absolute; width: 480px; height: auto; right: 3%; bottom: 5%; /*display: none;*/ }
7. Initialise the objects
Once the window and video is loaded, a JS <script> begins by grabbing the Canvas, its 2D drawing context and the video from the document. From here we can call a function we’ll recursively call ‘drawVideo()’, passing in all those iniltialised objects and the drawing surface width/height of the Canvas:
<script> window.onload=function(){ var canvas = document.getElementById("theCanvas"); var context = canvas.getContext("2d"); // grab canvas and 2D drawing context var video = document.getElementById("theVideo"); // grab the video element drawVideo(context, video, canvas.width, canvas.height); // calls drawVideo() function, passing all the objects }
8. Recursive drawing function
The drawVideo() function crucially calls drawImage() on the Canvas context, passing the current video frame. Here you can set a millisecond delay after the first pass to add a slower frame-rate effect when passed into setTimeout() to recursively call the function indefinitely, as long as the video is looped.
function drawVideo(context, video, width, height) { context.drawImage(video, 0, 0, width, height); // draws current video frame to canvas var delay = 100; // milliseconds delay for slowing framerate setTimeout(drawVideo, delay, context, video, width, height); // recursively calls drawVideo() again after delay } </script>