niklasvh / html2canvas

Screenshots with JavaScript
https://html2canvas.hertzen.com/
MIT License
30.58k stars 4.81k forks source link

Canvas ignores object-fit property #725

Open barocsi opened 9 years ago

barocsi commented 9 years ago

When using any object-fit setting, its being ignored and images are simply stretched to fill the space due to flexbox props.

.bt-create-post-images-container {
  min-width: 100%;
  background-color: #8f8f8f;
  height: 350px;
  overflow: hidden;
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
}

.bt-create-post-image-container {
  background-color: #8f8f8f;
  height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}

.bt-create-post-image-container > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  align-self: auto;
  vertical-align: middle;
}
<div class="bt-create-post-images-container" id="images">
  <div class="bt-create-post-image-container {{type == 'versus' && 'flex-versus' || ''}}">
    <img ng-show="show_left" ng-src="{{uri_left}}">
  </div>
  <div class="bt-create-post-image-container {{type == 'versus' && 'flex-versus' || ''}}">
    <img ng-show="show_right" ng-src="{{uri_right}}">
  </div>
</div>
zupabxl commented 8 years ago

Hi, any news/workaround on this issue? I really need the cover option; I could use a background-size cover (supposedly fixed in issue #288) but as the size of my div is undefined (100% width, 100% height), it's not working even with the last alpha build. Disclaimer: i'm an artist following js classes these days so I hope the solution is not too obvious. I can see many uses for html2canvas in my practice so thanks a lot anyway!

jpyamamoto commented 6 years ago

Are there updates regarding this issue? Has anyone found a workaround?

LanderBeeuwsaert commented 6 years ago

Hello, just to let you know that I needed this and hacked it to work in my project. I provide the code which works for me below. However this is a hack, I don't have the knowledge to integrate this into your project in a more proper way and give you a pull request:

      key: 'drawImage',
        value: function drawImage(image, source, destination) {
          /**START CUSTOM CODE**/

            var newWidth = 30;
            var newHeight = 30;
            var newX = destination.left;
            var newY = destination.top;

            // console.log(image, source, destination);
            if (source.width/destination.width > source.height/destination.height) {
                newWidth = destination.width;
                newHeight = source.height * (destination.width / source.width);
                newY = destination.top + (destination.height - newHeight) / 2;
            } else {
                newWidth = source.width * (destination.height / source.height);
                newHeight = destination.height;
                newX = destination.left + (destination.width - newWidth) / 2;
            }
          // console.log(newWidth, newHeight);

            this.ctx.drawImage(image, source.left, source.top, source.width, source.height,
              newX, newY,
              newWidth, newHeight);
            // destination.width,
            // destination.height * (source.height / source.width)
            //   destination.width, destination.height);

          /**END CUSTOM CODE**/
        }
ColinAmos commented 6 years ago

Take LanderBeeuwsaert's solution (by downloading html2canvas.js so you can edit its code like they did) and replace

if (source.width/destination.width > source.height/destination.height) {

with

if (source.width/destination.width < source.height/destination.height) {

That should get you your desired results. It worked for me, at least.

tanys123 commented 5 years ago

@LanderBeeuwsaert Can you explain the code?

LanderBeeuwsaert commented 5 years ago

Hello @tanys123 , honestly it's so long ago I have no idea anymore in detail how it works exactly.

diogocapela commented 4 years ago

Use version 1.0.0-alpha.9 and add a patch-package with @LanderBeeuwsaert code like this one html2canvas+1.0.0-alpha.9.patch:

diff --git a/node_modules/html2canvas/dist/html2canvas.js b/node_modules/html2canvas/dist/html2canvas.js
index 5f34081..66d1909 100644
--- a/node_modules/html2canvas/dist/html2canvas.js
+++ b/node_modules/html2canvas/dist/html2canvas.js
@@ -2443,7 +2443,22 @@ var CanvasRenderer = function () {
     }, {
         key: 'drawImage',
         value: function drawImage(image, source, destination) {
-            this.ctx.drawImage(image, source.left, source.top, source.width, source.height, destination.left, destination.top, destination.width, destination.height);
+            var newWidth = 30;
+            var newHeight = 30;
+            var newX = destination.left;
+            var newY = destination.top;
+
+            if (source.width/destination.width < source.height/destination.height) {
+                newWidth = destination.width;
+                newHeight = source.height * (destination.width / source.width);
+                newY = destination.top + (destination.height - newHeight) / 2;
+            } else {
+                newWidth = source.width * (destination.height / source.height);
+                newHeight = destination.height;
+                newX = destination.left + (destination.width - newWidth) / 2;
+            }
+
+            this.ctx.drawImage(image, source.left, source.top, source.width, source.height, newX, newY, newWidth, newHeight);
         }
     }, {
         key: 'drawShape',

Don't forget to import the version that it is not minified by providing the full path:

const html2canvas = require('html2canvas/dist/html2canvas.js');
logicalicy commented 3 years ago

FYI, there's a different solution/workaround, as I struggled with object-fit and object-position. Instead of using an img, use a div with following CSS:

background-image: url(<MY_SOURCE>);
background-size: <OBJECT_FIT>;
background-position: <OBJECT_POSITION>;
clevergod commented 3 years ago

FYI, there's a different solution/workaround, as I struggled with object-fit and object-position. Instead of using an img, use a div with following CSS:

background-image: url(<MY_SOURCE>);
background-size: <OBJECT_FIT>;
background-position: <OBJECT_POSITION>;

The picture will be blurred

Horbarz commented 3 years ago

@clevergod Do you have a fix for using object-fit property?

meiyasan commented 3 years ago

@niklasvh Hi, I am using version 0.41 for the moment. It includes "background-size:cover", but not "object-fit". Any plan to fix it ?

Using background-size is not satisfying as it comes after DOM (kind of slow compared to just using img)

theindianappguy commented 3 years ago

FYI, there's a different solution/workaround, as I struggled with object-fit and object-position. Instead of using an img, use a div with following CSS:

background-image: url(<MY_SOURCE>);
background-size: <OBJECT_FIT>;
background-position: <OBJECT_POSITION>;

This works

Rubinhuang9239 commented 3 years ago

FYI, there's a different solution/workaround, as I struggled with object-fit and object-position. Instead of using an img, use a div with following CSS:

background-image: url(<MY_SOURCE>);
background-size: <OBJECT_FIT>;
background-position: <OBJECT_POSITION>;

This works

No on iOS, background image will run into errors

MiguelALopez commented 2 years ago

@niklasvh do you think that a future patch will come for this bug ?

leonardoviada commented 1 year ago

FYI, there's a different solution/workaround, as I struggled with object-fit and object-position. Instead of using an img, use a div with following CSS:

background-image: url(<MY_SOURCE>);
background-size: <OBJECT_FIT>;
background-position: <OBJECT_POSITION>;

Does not work when you need to enable tainted canvas and CORS