javascript - 如何使用 HTML5 canvas 标签显示视频

标签 javascript canvas html5-canvas html5-video

我想使用 Canvas 显示视频,包括播放暂停功能,允许用户通过单击 Canvas 来切换播放,我还希望在视频暂停时在视频顶部绘制覆盖层。这是如何在 JavaScript 中完成的?

Canvas 可用于显示来自各种来源的视频。此示例演示如何将视频作为文件资源加载、显示并添加简单的点击屏幕播放/暂停切换。

只是一张图片

就 Canvas 而言,视频只是图像。您可以像任何图像一样绘制它。不同之处在于视频可以播放并且有声音。

获取 Canvas 和基本设置

// It is assumed you know how to add a canvas and correctly size it.
var canvas = document.getElementById("myCanvas"); // get the canvas from the page
var ctx = canvas.getContext("2d");
var videoContainer; // object to hold video and associated info

创建并加载视频

var video = document.createElement("video"); // create a video element
video.src = "urlOffVideo.webm"; 
// the video will now begin to load.
// As some additional info is needed we will place the video in a
// containing object for convenience
video.autoPlay = false; // ensure that the video does not auto play
video.loop = true; // set the video to loop.
videoContainer = {  // we will add properties as needed
     video : video,
     ready : false,   
};

与图像元素不同,视频不必完全加载即可显示在 Canvas 上。视频还提供了许多可用于监视视频状态的额外事件。

在本例中,我们希望知道视频何时可以播放。 oncanplay 表示已加载足够的视频来播放其中的一部分,但可能不足以播放到最后。

video.oncanplay = readyToPlayVideo; // set the event to the play function that 
                                  // can be found below

或者,您可以使用oncanplaythrough,它会在加载足够的视频时触发,以便可以播放到最后。

video.oncanplaythrough = readyToPlayVideo; // set the event to the play function that
                                         // can be found below

仅使用 canPlay 事件之一,而不是同时使用两者。

can play事件(相当于图片onload)

function readyToPlayVideo(event){ // this is a referance to the video
    // the video may not match the canvas size so find a scale to fit
    videoContainer.scale = Math.min(
                         canvas.width / this.videoWidth, 
                         canvas.height / this.videoHeight); 
    videoContainer.ready = true;
    // the video can be played so hand it off to the display function
    requestAnimationFrame(undateCanvas);
}
<小时/>

显示

视频不会在 Canvas 上自行播放。您需要为每个新帧绘制它。由于很难知道确切的帧速率以及帧速率何时发生,因此最好的方法是显示视频,就像以 60 fps 运行一样。如果帧速率较低,则只需将同一帧渲染两次。如果帧速率较高,则无法看到额外的帧,因此我们只需忽略它们。

视频元素只是一个图像元素,可以像任何图像一样绘制,您可以缩放、旋转、平移视频、镜像、淡入淡出、剪辑并仅显示部分,使用 a 绘制两次全局复合模式添加 FX,如变亮、屏幕等。

function updateCanvas(){
    ctx.clearRect(0,0,canvas.width,canvas.height); // Though not always needed 
                                                     // you may get bad pixels from 
                                                     // previous videos so clear to be
                                                     // safe
    // only draw if loaded and ready
    if(videoContainer !== undefined && videoContainer.ready){ 
        // find the top left of the video on the canvas
        var scale = videoContainer.scale;
        var vidH = videoContainer.video.videoHeight;
        var vidW = videoContainer.video.videoWidth;
        var top = canvas.height / 2 - (vidH /2 ) * scale;
        var left = canvas.width / 2 - (vidW /2 ) * scale;
        // now just draw the video the correct size
        ctx.drawImage(videoContainer.video, left, top, vidW * scale, vidH * scale);
        if(videoContainer.video.paused){ // if not playing show the paused screen 
            drawPayIcon();
        }
    }
    // all done for display 
    // request the next frame in 1/60th of a second
    requestAnimationFrame(updateCanvas);

}

基本播放暂停控制

现在我们已经加载并显示了视频,我们所需要的只是播放控件。我们将其设置为在屏幕上点击切换播放。当视频正在播放并且用户单击时,视频将暂停。暂停时单击即可恢复播放。我们将添加一个功能来使视频变暗并绘制播放图标(三 Angular 形)

function drawPayIcon(){
     ctx.fillStyle = "black";  // darken display
     ctx.globalAlpha = 0.5;
     ctx.fillRect(0,0,canvas.width,canvas.height);
     ctx.fillStyle = "#DDD"; // colour of play icon
     ctx.globalAlpha = 0.75; // partly transparent
     ctx.beginPath(); // create the path for the icon
     var size = (canvas.height / 2) * 0.5;  // the size of the icon
     ctx.moveTo(canvas.width/2 + size/2, canvas.height / 2); // start at the pointy end
     ctx.lineTo(canvas.width/2 - size/2, canvas.height / 2 + size);
     ctx.lineTo(canvas.width/2 - size/2, canvas.height / 2 - size);
     ctx.closePath();
     ctx.fill();
     ctx.globalAlpha = 1; // restore alpha
}    

现在播放暂停事件

function playPauseClick(){
     if(videoContainer !== undefined && videoContainer.ready){
          if(videoContainer.video.paused){                                 
                videoContainer.video.play();
          }else{
                videoContainer.video.pause();
          }
     }
}
// register the event
canvas.addEventListener("click",playPauseClick);
<小时/>

摘要

使用 Canvas 播放视频非常容易,实时添加效果也很容易。然而,在格式、播放和搜索方式上存在一些限制。 MDN HTMLMediaElement 是获取视频对象完整引用的地方。

在 Canvas 上绘制图像后,您可以使用 ctx.getImageData 来访问它包含的像素。或者,您可以使用 canvas.toDataURL 拍摄静态图片并下载。 (仅当视频来自可信来源并且不会污染 Canvas 时)。

<小时/>

请注意,如果视频有声音,那么播放它也会播放声音。

祝您视频愉快。

最佳答案

使用canvas显示视频

显示视频与显示图像非常相似。细微的差别与 onload 事件有关,并且您需要渲染每一帧视频,否则您只会看到一帧而不是动画帧。

下面的演示与示例有一些细微的差别。静音功能(在视频下单击静音/声音打开以切换声音)和一些错误检查,以捕获 IE9+ 和 Edge(如果它们没有正确的驱动程序)。我本来会使用 IE 支持的另一种格式,但找不到公共(public)领域的格式。

Note users of IE9+ and Edge. You may not be able to play the video format WebM as it needs additional drivers to play the videos. They can be found at tools.google.com Download IE9+ WebM support

// This code is from the example document on stackoverflow documentation. See HTML for link to the example.
// This code is almost identical to the example. Mute has been added and a media source. Also added some error handling incase the media load fails and a link to fix IE9+ and Edge suport.
// Code by Blindman67.



var mediaSource = "http://video.webmfiles.org/big-buck-bunny_trailer.webm";

var muted = true;
var canvas = document.getElementById("myCanvas"); // get the canvas from the page
var ctx = canvas.getContext("2d");
var videoContainer; // object to hold video and associated info
var video = document.createElement("video"); // create a video element
video.src = mediaSource;
// the video will now begin to load.
// As some additional info is needed we will place the video in a
// containing object for convenience
video.autoPlay = false; // ensure that the video does not auto play
video.loop = true; // set the video to loop.
video.muted = muted;
videoContainer = {  // we will add properties as needed
     video : video,
     ready : false,   
};
// To handle errors. This is not part of the example at the moment. Just fixing for Edge that did not like the ogv format video
video.onerror = function(e){
    document.body.removeChild(canvas);
    document.body.innerHTML += "<h2>There is a problem loading the video</h2><br>";
    document.body.innerHTML += "Users of IE9+ , the browser does not support WebM videos used by this demo";
    document.body.innerHTML += "<br><a href='https://tools.google.com/dlpage/webmmf/'> Download IE9+ WebM support</a> from tools.google.com<br> this includes Edge and Windows 10";
    
 }
video.oncanplay = readyToPlayVideo; // set the event to the play function that 
                                  // can be found below
function readyToPlayVideo(event){ // this is a referance to the video
    // the video may not match the canvas size so find a scale to fit
    videoContainer.scale = Math.min(
                         canvas.width / this.videoWidth, 
                         canvas.height / this.videoHeight); 
    videoContainer.ready = true;
    // the video can be played so hand it off to the display function
    requestAnimationFrame(updateCanvas);
    // add instruction
    document.getElementById("playPause").textContent = "Click video to play/pause.";
    document.querySelector(".mute").textContent = "Mute";
}

function updateCanvas(){
    ctx.clearRect(0,0,canvas.width,canvas.height); 
    // only draw if loaded and ready
    if(videoContainer !== undefined && videoContainer.ready){ 
        // find the top left of the video on the canvas
        video.muted = muted;
        var scale = videoContainer.scale;
        var vidH = videoContainer.video.videoHeight;
        var vidW = videoContainer.video.videoWidth;
        var top = canvas.height / 2 - (vidH /2 ) * scale;
        var left = canvas.width / 2 - (vidW /2 ) * scale;
        // now just draw the video the correct size
        ctx.drawImage(videoContainer.video, left, top, vidW * scale, vidH * scale);
        if(videoContainer.video.paused){ // if not playing show the paused screen 
            drawPayIcon();
        }
    }
    // all done for display 
    // request the next frame in 1/60th of a second
    requestAnimationFrame(updateCanvas);
}

function drawPayIcon(){
     ctx.fillStyle = "black";  // darken display
     ctx.globalAlpha = 0.5;
     ctx.fillRect(0,0,canvas.width,canvas.height);
     ctx.fillStyle = "#DDD"; // colour of play icon
     ctx.globalAlpha = 0.75; // partly transparent
     ctx.beginPath(); // create the path for the icon
     var size = (canvas.height / 2) * 0.5;  // the size of the icon
     ctx.moveTo(canvas.width/2 + size/2, canvas.height / 2); // start at the pointy end
     ctx.lineTo(canvas.width/2 - size/2, canvas.height / 2 + size);
     ctx.lineTo(canvas.width/2 - size/2, canvas.height / 2 - size);
     ctx.closePath();
     ctx.fill();
     ctx.globalAlpha = 1; // restore alpha
}    

function playPauseClick(){
     if(videoContainer !== undefined && videoContainer.ready){
          if(videoContainer.video.paused){                                 
                videoContainer.video.play();
          }else{
                videoContainer.video.pause();
          }
     }
}
function videoMute(){
    muted = !muted;
	if(muted){
         document.querySelector(".mute").textContent = "Mute";
    }else{
         document.querySelector(".mute").textContent= "Sound on";
    }


}
// register the event
canvas.addEventListener("click",playPauseClick);
document.querySelector(".mute").addEventListener("click",videoMute)
body {
    font :14px  arial;
    text-align : center;
    background : #36A;
}
h2 {
    color : white;
}
canvas {
    border : 10px white solid;
    cursor : pointer;
}
a {
  color : #F93;
}
.mute {
    cursor : pointer;
    display: initial;   
}
<h2>Basic Video & canvas example</h2>
<p>Code example from Stackoverflow Documentation HTML5-Canvas<br>
<a href="https://stackoverflow.com/documentation/html5-canvas/3689/media-types-and-the-canvas/14974/basic-loading-and-playing-a-video-on-the-canvas#t=201607271638099201116">Basic loading and playing a video on the canvas</a></p>
<canvas id="myCanvas" width = "532" height ="300" ></canvas><br>
<h3><div id = "playPause">Loading content.</div></h3>
<div class="mute"></div><br>

关于javascript - 如何使用 HTML5 canvas 标签显示视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38710125/

相关文章:

javascript - 无法让 Jquery .each 函数正常工作

javascript - 将 const 函数代码从 JSX 转换为 TSX

javascript - 使用 API 将文件上传到预先设置的 Google Drive 帐户?

java - 将 Vector 转换为 HTML5 Canvas(DXF 到 Canvas 坐标)

JavaScript 将图像数据放在 Canvas 上

javascript - 根据窗口宽度更改 Chart.js 选项

javascript - 火力地堡 : Anonymous authentication - How to set identifier?

android - 将 Canvas 图像保存到 SQLite?

javascript - 在 Canvas 中旋转 Sprite

javascript - 有哪些 HTML5 Canvas 像素检测和图像处理库?