Drawing video on canvas

試著忘記壹切 提交于 2019-12-24 23:16:51

问题


I'm trying to draw a video from video element on canvas. I wrote the following JS code:

$(function () {
    var video = $("#video");
    video.bind("loadedmetadata", function () {
        var vw = this.videoWidth;
        var vh = this.videoHeight;
        var canvas = $('#canvas');
        canvas.width(vw).height(vh);
        var context = canvas.getContext("2d");

        video.addEventListener("play", function () { draw(video, context, vw, vh); }, false);
    });
});
function draw(video, context, vw, vh)
{
    if (video.paused || video.ended)
    {              
        return false;
    }

    context.drawImage(video, 0, 0, vw, vh);
    setTimeout(draw, 20, video, context, vw, vh);
}

This is my HTML:

<body>
<video id="video" autoplay controls>
    <source src="src1.avi" />
    <source src="src2.mov" />
    <source src="src3.ogg" />
    <source src="src4.avi" />
</video>
<canvas id="canvas">
    Please update your browser.
</canvas>

JSFiddle here

I can see the video playing, but it's not being redrawn onto the canvas. Where's my mistake?


回答1:


Using jQuery with elements such as video and canvas (and audio) is asking for trouble if you are not absolute sure what you're doing.

You are for example calling getContext(), videoWidth, videoHeight etc. on the jQuery objects which won't work well, and also mixing vanilla JavaScript with jQuery such as bind() and addEventListener().

My first recommendation is to use plain vanilla JavaScript when working with these elements as not only will life become less troublesome, but you'll also gain some performance which can be critical with these elements.

Second, always use requestAnimationFrame with video and canvas. There is no chance synching these properly with setTimeout/setInterval. rAF will make sure a frame is updated to monitor at the exact right time. With video you can toggle the speed as video rarely is above 30 FPS (in Europe it's 25 FPS), and it will give you some extra performance space.

Here is a working code (still need clean-up though...):

HTML - add preload = "auto" to the video tag to catch meta data before playing:

<video id="video" preload=auto autoplay controls>

JavaScript

var video = $("#video")[0];               // video element itself is at index 0 
var vw;
var vh;

var canvas = $('#canvas')[0];             // canvas element itself is at index 0
var context = canvas.getContext("2d");    // getContext on canvas element itself

// setup canvas when metadata is available
video.addEventListener("loadedmetadata", function() {
    vw = this.videoWidth || this.width;   // these are on video element itself
    vh = this.videoHeight || this.height;
    canvas.width = vw
    canvas.height = vh;
}, false);

// call it straight, use global (or parent) variables
video.addEventListener("play", draw, false);

function draw() {
    if (video.paused || video.ended) {
        return;
    }

    context.drawImage(video, 0, 0, vw, vh);

    requestAnimationFrame(draw);  // loop anim. using rAF
}


来源:https://stackoverflow.com/questions/27079583/drawing-video-on-canvas

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!