javascript HTML5:疯狂的画布绘制图像大小

s2j5cfk0  于 2023-01-11  发布在  Java
关注(0)|答案(4)|浏览(338)

我有下一个html模板:

<div className="page">
    <video id="video" autoPlay/>
    <canvas id="canvas"/>
    <div class="btn-wrapper">
        <button onClick={this._takePhoto}>Snap Photo</button>
    </div>
</div>

这是我的应用程序的屏幕截图。在顶部你可以看到<video>,在底部<canvas/>(焦点在devtools)。

**问题:**要将<video/>图片绘制为<canvas/>,我应该使用以下奇怪的系数:

const canvas = document.getElementById('canvas'),
          context = canvas.getContext("2d"),
          video = document.getElementById('video');
    //QUESTION: why?!
    const widthCoef = 2.1,
          heigthCoef = 3;
    context.drawImage(video, 
                      0, 
                      0, 
                      video.clientWidth * widthCoef, 
                      video.clientHeight * heightCoef, 
                      0, 
                      0, 
                      canvas.clientWidth, 
                      canvas.clientHeight);

**问题:**如果<video/><canvas/>具有相同的宽度/高度,为什么要使用系数?

如果我做同样的事但没有系数

context.drawImage(video, 0, 0, video.clientWidth, video.clientHeight, 0, 0, canvas.clientWidth, canvas.clientHeight); //OR
context.drawImage(video, 0, 0, video.clientWidth, video.clientHeight, 0, 0, video.clientWidth, video.clientHeight); //OR
context.drawImage(video, 0, 0, canvas.clientWidth, canvas.clientHeight, 0, 0, canvas.clientWidth, canvas.clientHeight);

我得到一张放大的图片:

更新

我的新调整大小版本:

_resizeCanvas() {
    const canvas = document.getElementById('canvas'),
        video = document.getElementById('video');
    const width = +window.getComputedStyle(video, null).getPropertyValue('width').replace('px', ''),
          height = +window.getComputedStyle(video, null).getPropertyValue('height').replace('px', '');
    video.width = width;
    video.height = height;
    canvas.width = width;
    canvas.height = height;
},

更新2 -添加小提琴示例

Here is my fiddle example

x0fgdtte

x0fgdtte1#

这些幻数系数对应于video对象大小和画布大小之间的比率。
假设您的video大小为(400 x 300),并且您希望将其显示在大小为(200 x 150)的画布上。

context.drawImage(video,0,0,200,150);

它将调整整个video的大小以适合画布。
但是,您使用的是drawImage()的剪切版本。前四个坐标参数描述剪切参数。例如,在以下情况下,它占用完整video的四分之一:

context.drawImage(video,0,0,200,150,0,0,200,150);
  • 根据更新的问题编辑 *

由于属性canvas.clientWidthcanvas.clientHeight大于canvas.widthcanvas.height,因此图像被剪切。这是由于CSS display: flex;造成的。要显示完整图像,请用途:

context.drawImage(video, 0, 0, canvas.width, canvas.height);
lg40wkob

lg40wkob2#

这里是我的问题的工作小提琴。我还没有时间去调查为什么它没有在我的应用程序上工作。将在不久的将来更新。

  • 为了让它们都能在JSFiddle上工作,我添加了HTML5-video - autoplay选项,不知道如何在StackOverflow上做同样的事情 *
  1. JS + JQuery https://jsfiddle.net/ytLgebvg/42/
    1.Reactjs https://jsfiddle.net/69z2wepo/18812/

JS+联合查询

function redraw(canvas) {
    var context = canvas.getContext("2d");
    context.strokeStyle = 'blue';
    context.lineWidth = '5';
    context.strokeRect(0, 0, window.innerWidth, window.innerHeight);
}
		
function resizeCanvas(canvas, width, height) {
    var canvasClWidthBefore = +window.getComputedStyle(canvas, null).getPropertyValue('width').replace('px', ''),
        canvasClHeightBefore = +window.getComputedStyle(canvas, null).getPropertyValue('height').replace('px', '');
    alert('canvas cl before: ' + canvasClWidthBefore + 'x' + canvasClHeightBefore);
    
    canvas.width = width;
    canvas.height = height;
    
    var canvasClWidthAfter = +window.getComputedStyle(canvas, null).getPropertyValue('width').replace('px', ''),
        canvasClHeightAfter = +window.getComputedStyle(canvas, null).getPropertyValue('height').replace('px', '');
    alert('canvas cl before: ' + canvasClWidthAfter + 'x' + canvasClHeightAfter);
    
    redraw(canvas);
}

$(document).ready(function() {
	// Grab elements, create settings, etc.
	var canvas = document.getElementById("canvas"),
	    context = canvas.getContext("2d"),
	    video = document.getElementById("video"),
	    videoObj = { "video": true };
	navigator.webkitGetUserMedia(videoObj, function(stream){
	    video.src = window.URL.createObjectURL(stream);
	    video.play();
	}, function() {});
    
    $('#snap-photo-btn').click(function() {
        const canvas = document.getElementById("canvas"),
              context = canvas.getContext("2d"),
              video = document.getElementById("video");
        $('#canvas').removeClass('photoMode');
        $('#canvas').addClass('editMode');
        $('#video').removeClass('photoMode');
        $('#video').addClass('editMode');
        var videoClWidth = +window.getComputedStyle(video, null).getPropertyValue('width').replace('px', ''),
            videoClHeight = +window.getComputedStyle(video, null).getPropertyValue('height').replace('px', '');       
        
        resizeCanvas(canvas, videoClWidth, videoClHeight);
        
		var canvasWidth = canvas.width,
            canvasHeight = canvas.height;     


            
        alert('canvas: ' + canvasWidth + 'x' + canvasHeight);
        alert('video cl: ' + videoClWidth + 'x' + videoClHeight);
        context.drawImage(video, 0, 0, canvasWidth, canvasHeight);
    });
});
.main {
    position: relative;
}

video {
    position: absolute;
    top: 0;
    left: 0;
    min-width: 100%;
    min-height: 100%;
    height: auto;
    width: auto;
}
video.photoMode { z-index: 1000; }
video.editMode { z-index: -1000; }

canvas {
    /* position: absolute;
    top: 0;
    left: 0;
    min-width: 100%;
    min-height: 100%;
    height: auto;
    width: auto; */
}
canvas.photoMode { z-index: -1000; }
canvas.editMode { z-index: 1000; }

.btn-wrapper {
    position: absolute;
    width: 100%;
    top: 0;
    left: 0;
    display: flex;
    flex-direction: row;
    justify-content: center;
    z-index: 2000;    
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main">
    <video class="photoMode" id="video" autoPlay></video>
    <canvas class="photoMode" id="canvas"></canvas>
    <div class="btn-wrapper">
        <button id="snap-photo-btn">Snap Photo</button>
    </div>
</div>

React

一个一个三个一个一个一个一个一个四个一个一个一个一个一个五个一个

ncgqoxb0

ncgqoxb03#

我对此做了一些测试,似乎第3个和第4个参数,即您要从源中获取的区域的宽度和高度,是相对于媒体的原始大小,而不是显示媒体的元素的大小。因此,它基于视频的原始尺寸,而不是视频元素的宽度和高度。
我很惊讶非剪辑版本不起作用。如果你这样做的话,它似乎应该起作用:

context.drawImage(video, 0, 0, canvas.clientWidth, canvas.clientHeight);

这将获取完整的视频图像,并将其显示在画布的左上角以及画布的整个宽度和高度上。

y1aodyip

y1aodyip4#

我在我的React应用程序中也遇到过这个问题。我的解决方案是在画布标签上设置宽度和高度 prop 。

<div className="page">
    <video id="video" autoPlay/>
    <canvas id="canvas" width="640" height="360"/>
    <div class="btn-wrapper">
        <button onClick={this._takePhoto}>Snap Photo</button>
    </div>
</div>

并使用video.widht\video.height填充上下文:

let video = document.getElementById("video")
let width = video?.width
let height = video?.height
          
ctx.drawImage(video, 0, 0, width, height);

相关问题