简体   繁体   English

在视频上叠加 canvas,canvas 没有读取视频的高宽属性

[英]Overlaying canvas on a video, canvas is not reading video height and width attributes

So I am trying to overlay a HTML canvas element over a 500x500 video.所以我试图在 500x500 视频上覆盖 HTML canvas 元素。 I always want the video to be 500x500.我一直希望视频为 500x500。 In my code, I've set the canvas height and width to be the same as the video height and width so they overlay right on top of one another.在我的代码中,我将 canvas 的高度和宽度设置为与视频的高度和宽度相同,因此它们彼此重叠。 Unfortunately, whenever I run this, the canvas element always outputs a width of 800 and a height of 600. I believe this may have something to do with the size of the original video.不幸的是,每当我运行这个时,canvas 元素总是输出 800 的宽度和 600 的高度。我相信这可能与原始视频的大小有关。 However, I'm really not sure why my canvas elements won't pick up on those values.但是,我真的不确定为什么我的 canvas 元素不会接受这些值。 I also tried directly setting my canvas height and width to 500 but when I do that it won't overlay right on top of the video.我还尝试直接将我的 canvas 高度和宽度设置为 500,但是当我这样做时,它不会覆盖在视频的正上方。 I was just wondering if anyone knew why this might be occurring and if there is anything striking out to you in my code where I am setting these elements that is causing this to occur.我只是想知道是否有人知道为什么会发生这种情况,以及在我的代码中是否有什么让你印象深刻的地方,我正在设置这些导致这种情况发生的元素。 I have also looked at other stack overflow posts before making this one and tried to get some context from those solutions but nothing has worked for me yet.在制作这篇文章之前,我还查看了其他堆栈溢出帖子,并尝试从这些解决方案中获取一些上下文,但对我来说还没有任何效果。

This is my.php file:这是我的.php 文件:

 document.getElementById("bounding-tool").addEventListener("click", function() { const canvas = document.getElementById("canvas"); canvas.style.visibility = "visible"; canvas.style.opacity = 0; //canvas.style.position = relative; }) function create_canvas() { const video_frame = document.getElementById("video_frame"); //const video = document.getElementById("video"); const video = document.querySelector("video#video, #video video"); //let rect = video.getBoundingClientRect(); //console.log(rect.bottom, rect.left, rect.top, rect.right) video.addEventListener('loadedmetadata', (event) => { const canvas = document.getElementById("canvas"); canvas.height = 438; canvas.width = 584; const { videoWidth, videoHeight } = video; // We're assuming that the width is the larger than the height of video. const shrinkFactor = canvas.height / videoHeight * 100; const dimensions = { width: Math.floor(videoWidth / 100 * shrinkFactor), height: Math.floor(videoHeight / 100 * shrinkFactor) }; const offset = (dimensions.width - canvas.width) / 2; var context = canvas.getContext('2d'); const loop = () => { context.save(); context.fillRect(0,0,video.VideoHeight,video.videoWidth); context.drawImage(video,0,0,video.VideoHeight,video.videoWidth); create_bounding_tool(canvas); video_frame.append(canvas); canvas.style.visibility = "hidden"; //canvas.style.opacity = "0"; context.restore(); context.fillRect(0,0,canvas.height,canvas.width); // bind event handler to clear button //context.clearRect(0, 0, canvas.width, canvas.height);*/ } loop(); }); }
 #video_frame{ display: inline-flex; position: relative; margin-left: 7em; width: 584px; height: 438px; flex: 0 0 584px; margin-right: 0.5rem; margin-top: 7em; } #playback_frame{ display:flex; } #video{ width: 100%; height: 100%; object-fit: cover; /*opacity: 0.5;*/ border: 4px solid #0033A0; /*box-shadow: 0px 0px 7px grey;*/ } #canvas{ position: absolute; /* margin-top: 4.4em;*/ top: 0; left: 0; width: 100%; height: 100%; /*pointer-events: none;*/ opacity: 0.5; border: 5px solid red; }
 <head> <title> </title> <meta charset="UTF-8"> <meta name="description" content="Video Determiner"> <meta name="keywords" content="Video Determiner" /> <meta name="author" content="Video Determiner" /> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link href="../css/style.css" rel="stylesheet"> <link href="https://vjs.zencdn.net/7.10.2/video-js.css" rel="stylesheet" /> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/videojs-seek-buttons/dist/videojs-seek-buttons.css"/> </head> <div id="video_frame"> <video class = "video-js vjs-big-play-centered" controls id="video" width = "584" height = "438" data-setup="{}"> <source id ="source" src="http://grochtdreis.de/fuer-jsfiddle/video/sintel_trailer-480.mp4" type="video/mp4""> <p class="vjs-no-js"> To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a></p> </video> <canvas class = "video-wrapper_canvas" id = "canvas"></canvas> </div>

I've made a demo below which shows the video element with a canvas overlay.我在下面做了一个演示,它显示了带有 canvas 覆盖的视频元素。 The canvas renders the video with the same position and size as the video itself. canvas 使用与视频本身相同的 position 和大小渲染视频。 If you Run code snippet and then Full page you'll get the best result.如果您运行代码片段,然后是整,您将获得最佳结果。

To make sure that both the video and canvas are the same size, set the container to 500x500 with the video and canvas to 100% width and height.为确保视频和 canvas 的大小相同,请将视频容器设置为 500x500,将 canvas 设置为 100% 的宽度和高度。

I've use object-fit: cover;我使用object-fit: cover; to make the video fully expand the width and height of the container.使视频充分扩展容器的宽度和高度。

Now, the video might be a lot larger than 500x500, so we'll need to convert a (for example) 1920x1080 video to a 500x500 viewport.现在,视频可能比 500x500 大很多,因此我们需要将(例如)1920x1080 视频转换为 500x500 视口。 To do this we'll need to make some calculations.为此,我们需要进行一些计算。

We start off by calculating the shrink factor.我们从计算收缩系数开始。 The height of the video will be the same height of the canvas, but the width of the video must shrink the same amount of pixels to make sure that the aspect ratio of the video stays the same.视频的高度将与 canvas 的高度相同,但视频的宽度必须缩小相同数量的像素,以确保视频的纵横比保持不变。

Therefor we calculate height of canvas / height of video x 100 .因此,我们计算height of canvas / height of video x 100 This gives us percentage that the video must shrink to fit the height of the canvas while keeping the right aspect ratio.这为我们提供了视频必须缩小以适应 canvas 的高度同时保持正确纵横比的百分比。

Now because the width of the video is still larger than the width of the canvas, we'll need to offset the video a bit to the left to center our video.现在因为视频的宽度仍然大于 canvas 的宽度,我们需要将视频向左偏移一点以使视频居中。 We do this by doing (new video width - canvas width) / 2 .我们这样做(new video width - canvas width) / 2 This is the number in pixels the video needs to move left.这是视频需要向左移动的像素数。

Use these values to draw the video in canvas element with the right dimensions.使用这些值在 canvas 元素中绘制具有正确尺寸的视频。

 const video = document.getElementById('video'); const canvas = document.getElementById('canvas'); canvas.height = 500; canvas.width = 500; const context = canvas.getContext('2d'); video.addEventListener('loadedmetadata', () => { const { videoWidth, videoHeight } = video; // We're assuming that the width is the larger than the height of video. const shrinkFactor = canvas.height / videoHeight * 100; const dimensions = { width: Math.floor(videoWidth / 100 * shrinkFactor), height: Math.floor(videoHeight / 100 * shrinkFactor) }; const offset = (dimensions.width - canvas.width) / 2; const loop = () => { context.clearRect( 0, 0, canvas.width, canvas.height ); context.drawImage( video, 0 - offset, // Move it to the left to compensate for the width. 0, dimensions.width, dimensions.height ); requestAnimationFrame(loop); }; loop(); }); const compare = document.getElementById('compare'); compare.addEventListener('input', event => { const value = event.target.value; video.style.opacity = 1 - Number(value); canvas.style.opacity = value; });
 body { display: flex; align-items: flex-start; }.video-wrapper { position: relative; width: 500px; height: 500px; flex: 0 0 500px; margin-right: 0.5rem; }.video-wrapper__video { width: 100%; height: 100%; object-fit: cover; opacity: 0.5; border: 5px solid blue; }.video-wrapper__canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; opacity: 0.5; border: 5px solid red; }.slider { padding: 1rem; border: 1px solid #d0d0d0; border-radius: 3px; background-color: #f0f0f0; margin-left: 0.5rem; }.slider label { display: flex; font-family: sans-serif; }.label-video { color: blue; }.label-canvas { color: red; }
 <div class="video-wrapper"> <video class="video-js vjs-big-play-centered video-wrapper__video" controls id="video" width="500" height="500" data-setup="{}"> <source src="http://grochtdreis.de/fuer-jsfiddle/video/sintel_trailer-480.mp4"/> </video> <canvas class="video-wrapper__canvas" id="canvas"></canvas> </div> <div class="slider"> <label> <span class="label-video">Video</span> <input id="compare" type="range" min="0.1" max="0.9" step="0.1" value="0.5"> <span class="label-canvas">Canvas</span> </label> </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM