将画布覆盖在视频上,画布不会读取视频的高度和宽度属性



所以我试图在500x500视频上覆盖一个HTML画布元素。我一直希望视频是500x500。在我的代码中,我已经将画布的高度和宽度设置为与视频的高度和宽相同,这样它们就可以叠加在一起。不幸的是,每当我运行这个程序时,canvas元素总是输出宽度800和高度600。我相信这可能与原始视频的大小有关。然而,我真的不确定为什么我的画布元素不会接受这些值。我还尝试直接将画布的高度和宽度设置为500,但当我这样做时,它不会覆盖在视频的顶部。我只是想知道是否有人知道为什么会发生这种情况,以及在我设置这些元素的代码中是否有任何东西让你大吃一惊。在做这篇文章之前,我也看过其他堆栈溢出的帖子,并试图从这些解决方案中获得一些上下文,但对我来说还没有任何效果。

这是我的.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>

我在下面做了一个演示,展示了带有画布覆盖的视频元素。画布以与视频本身相同的位置和大小渲染视频。如果运行代码片段,然后整页您将获得最佳结果。

要确保视频和画布大小相同,请将容器设置为500x500,并将视频和画布设置为100%的宽度和高度。

我使用object-fit: cover;使视频完全扩展了容器的宽度和高度。

现在,视频可能比500x500大得多,因此我们需要将(例如(1920x1080视频转换为500x500视口。要做到这一点,我们需要做一些计算。

我们从计算收缩因子开始。视频的高度将与画布的高度相同,但视频的宽度必须收缩相同数量的像素,以确保视频的纵横比保持不变。

因此我们计算了CCD_ 2。这为我们提供了视频必须收缩以适应画布高度的百分比,同时保持正确的纵横比。

现在,因为视频的宽度仍然大于画布的宽度,我们需要将视频向左偏移一点,以使视频居中。我们通过执行(new video width - canvas width) / 2来做到这一点。这是视频向左移动所需的像素数。

使用这些值可以绘制具有正确尺寸的画布中的视频元素。

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>

最新更新