Get Off My Lawn Get Off My Lawn - 18 days ago 7
HTML Question

Crop video on canvas

I am getting

video
from the user's camera, and displaying it on a 1:1 square. I then have a button that takes a picture and draws it to a 1:1 canvas, the issue is that it isn't drawn in the same location on the canvas. How can I achieve this?

Here is a running example:

https://jsfiddle.net/90d3ar1m/

Here is the HTML:

<!doctype html>
<html>

<head>
<title>Camera</title>
<meta http-equiv="Content-Security-Policy" content="default-src * data: gap: https://ssl.gstatic.com 'unsafe-inline'; style-src * 'unsafe-eval'; media-src 'self' blob:">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/camera.css">
</head>

<body>
<div class="container">
<div class="camera">
<video id="monitor" autoplay></video>
</div>
<canvas id="photo"></canvas>
<input type=button value="&#x1F4F7;" onclick="snapshot()">
</div>
<script type="text/javascript" src="js/plugins/jquery.min.js"></script>
<script type="text/javascript" src="js/dist/pages/camera.js"></script>
</body>

</html>


Here is the CSS:

video {
width: 500px;
height: 500px;
object-fit: cover;
object-position: center;
}

.camera {
width: 500px;
height: 500px;
overflow: hidden;
}


Here is the TypeScript:

let canvas: HTMLCanvasElement;
let video: HTMLVideoElement;
$(window).on('load', async event => {
video = <HTMLVideoElement>document.getElementById('monitor');
canvas = <HTMLCanvasElement>document.getElementById('photo');

video.srcObject = await navigator.mediaDevices.getUserMedia({ video: true });
video.onloadedmetadata = () => {
canvas.width = 500;
canvas.height = 500;
}

});

function snapshot() {
canvas.getContext('2d').drawImage(video, 0, 0);
}

Answer

Your problem seems to be caused by the fact that the video element keeps the aspect ratio of the video, while the canvas does not. Also remember that ctx.drawImage takes up to eight positional and size arguments:

context.drawImage(img/vid,sx,sy,swidth,sheight,x,y,width,height);

I did some testing, and found this to work pretty well, but your mileage may vary: .drawImage(video,80,0,480,500,0,0,500,520);

I made a jsFiddle with these numbers, check it out to see if it works for you.

W3Schools has some great documentation on how these work, I suggest reading that: http://www.w3schools.com/tags/canvas_drawimage.asp

You could probably use the video's videoWidth and videoHeight attributes to calculate which numbers you need in drawImage for different aspect ratio source videos

Comments