...">
All geek questions in one place

HTML5: crazy drawImage canvas size

I have the following html template:

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

Here is a screenshot of my application. At the top you can see <video> and at the bottom <canvas/> (focus in devtools).

enter image description here

Problem: draw a <video/> image on <canvas/> I have to use these weird coefficients:

  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); 

Question: why should I use coefficients if <video/> and <canvas/> have the same width / height?


If I do the same, but without coefficients, for example

 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); 

I get a larger image:

enter image description here

UPDATE

My new version for resizing:

 _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; }, 

UPDATE 2 - add a sample script

Here is my sample script

+3
javascript css html5 html5-canvas html5-video
Volodymyr bakhmatiuk Oct 20 '15 at 14:22
source share
3 answers

These magic coefficients correspond to the ratio between the size of the video object and the size of the canvas.

Suppose your size is video (400 x 300) and you want to display it on canvas in size (200 x 150) . This can only be done:

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

It will resize the video to fit the canvas.

However, you are using the drawImage() version of drawImage() . The first four coordinate arguments describe the clipping parameters. For example, in the following case, a quarter of the full video is required:

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

Edit as per updated question

The image is cropped because the properties of canvas.clientWidth and canvas.clientHeight larger than canvas.width and canvas.height . This is due to CSS display: flex; . To show the use of the full image:

 context.drawImage(video, 0, 0, canvas.width, canvas.height); 
+2
Orest Hera Oct 20 '15 at 14:46
source share

Here are the working scripts for my problem. I have not had time to investigate why it does not work in my application. Will be updated in the near future.

To make them work on JSFiddle, I added an HTML5-video - autoplay parameter HTML5-video - autoplay , I don’t know how to do the same in StackOverflow

  • JS + JQuery https://jsfiddle.net/ytLgebvg/42/
  • React.js https://jsfiddle.net/69z2wepo/18812/

Js + jquery

 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> 

To react

 var Hello = React.createClass({ getInitialState() { return { photoMode: true }; }, render: function() { const clazz = this.state.photoMode ? 'photoMode' : 'editMode'; return ( <div className="main"> <video className={clazz} id="video" autoPlay></video> <canvas className={clazz} id="canvas"></canvas> <div className="btn-wrapper"> <button id="snap-photo-btn" onClick={this._snapPhoto}>Snap Photo</button> </div> </div> ); }, componentDidMount() { 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() {}); }, _snapPhoto() { const canvas = document.getElementById("canvas"), context = canvas.getContext("2d"), video = document.getElementById("video"); var videoClWidth = +window.getComputedStyle(video, null).getPropertyValue('width').replace('px', ''), videoClHeight = +window.getComputedStyle(video, null).getPropertyValue('height').replace('px', ''); this._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); this.setState({photoMode: false}); }, _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 after: ' + canvasClWidthAfter + 'x' + canvasClHeightAfter); this._redraw(canvas); }, _redraw(canvas) { var context = canvas.getContext("2d"); context.strokeStyle = 'blue'; context.lineWidth = '5'; context.strokeRect(0, 0, window.innerWidth, window.innerHeight); } }); ReactDOM.render( <Hello />, document.getElementById('container') ); 
 .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 {} 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://facebook.imtqy.com/react/js/jsfiddle-integration-babel.js"></script> <div id="container"> <!-- This element contents will be replaced with your component. --> </div> 
+1
Volodymyr bakhmatiuk Oct 21 '15 at 10:36
source share

I did some testing on this, and it seems to me that the 3rd and 4th parameters, which are the width and height of the area that you want to take from the source, refer to the original size of the medium, and not to the size of the element that displays carrier. Thus, it is based on the original dimensions of your video, and not on the width and height of your video element.

I am surprised that the non-cropping version does not work. It seems like it should, if you do:

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

This should display the full video image and display it in the upper left corner of the canvas and over the entire width and height of the canvas.

0
BurningLights Oct 20 '15 at 14:56
source share

Source: https://habr.com/ru/post/1501093/

More articles:

  • Wait until the form is completed. - c #
  • Using Lua to work with excel - lua
  • Htaccess Filesmatch General Information - http-status-code-403
  • AngularJS: how to open a modal view over a view in response to a hash change (ngView / $ routeProvider) - javascript
  • Problems with scaling over HTML 5 canvas 5 - javascript
  • What kind of optimization does the Clojure REPL perform for this block of code? - clojure
  • Understand how to calculate the sum at compile time - c ++
  • Python django, how to check if query result returned result - python
  • Pass a QImage object between class methods - c ++
  • C ++ Diamond Inheritance - c ++

All Articles

Geek Questions | 2019