Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tutorial: How to support object-fit: contain and object-fit: cover #3072

Open
raphaelbadia opened this issue May 30, 2023 · 9 comments · May be fixed by #3218
Open

Tutorial: How to support object-fit: contain and object-fit: cover #3072

raphaelbadia opened this issue May 30, 2023 · 9 comments · May be fixed by #3218

Comments

@raphaelbadia
Copy link

Hi! 👋

Firstly, thanks for your work on this project! 🙂

Today I used patch-package to patch html2canvas@1.4.1 for the project I'm working on.

I noticed reading other issues (#2541, #2442, #725) that this property was not supported.

Here is the diff that solved my problem:

diff --git a/node_modules/html2canvas/dist/html2canvas.js b/node_modules/html2canvas/dist/html2canvas.js
index 84cb30d..8b8bc50 100644
--- a/node_modules/html2canvas/dist/html2canvas.js
+++ b/node_modules/html2canvas/dist/html2canvas.js
@@ -3028,6 +3028,22 @@
         }
     };
 
+    var objectFit = {
+        name: 'object-fit',
+        initialValue: 'fill',
+        prefix: false,
+        type: 2 /* IDENT_VALUE */,
+        parse: function (_context, overflow) {
+            switch (overflow) {
+                case 'contain':
+                    return "contain" /* BREAK_WORD */;
+                case 'cover':
+                default:
+                    return "cover" /* NORMAL */;
+            }
+        }
+    };
+
     var paddingForSide = function (side) { return ({
         name: "padding-" + side,
         initialValue: '0',
@@ -3665,6 +3681,7 @@
             this.overflowX = overflowTuple[0];
             this.overflowY = overflowTuple[overflowTuple.length > 1 ? 1 : 0];
             this.overflowWrap = parse(context, overflowWrap, declaration.overflowWrap);
+            this.objectFit = parse(context, objectFit, declaration.objectFit);
             this.paddingTop = parse(context, paddingTop, declaration.paddingTop);
             this.paddingRight = parse(context, paddingRight, declaration.paddingRight);
             this.paddingBottom = parse(context, paddingBottom, declaration.paddingBottom);
@@ -6803,13 +6820,52 @@
             });
         };
         CanvasRenderer.prototype.renderReplacedElement = function (container, curves, image) {
+            const objectFit = container.styles.objectFit;
+
             if (image && container.intrinsicWidth > 0 && container.intrinsicHeight > 0) {
                 var box = contentBox(container);
                 var path = calculatePaddingBoxPath(curves);
                 this.path(path);
                 this.ctx.save();
                 this.ctx.clip();
-                this.ctx.drawImage(image, 0, 0, container.intrinsicWidth, container.intrinsicHeight, box.left, box.top, box.width, box.height);
+
+                let newWidth;
+                let newHeight;
+                let newX = box.left;
+                let newY = box.top;
+
+                function getObjectFitSize(contains /* true = contain, false = cover */, containerWidth, containerHeight, width, height) {
+                    var doRatio = width / height;
+                    var cRatio = containerWidth / containerHeight;
+                    var targetWidth = 0;
+                    var targetHeight = 0;
+                    var test = contains ? (doRatio > cRatio) : (doRatio < cRatio);
+
+                    if (test) {
+                        targetWidth = containerWidth;
+                        targetHeight = targetWidth / doRatio;
+                    } else {
+                        targetHeight = containerHeight;
+                        targetWidth = targetHeight * doRatio;
+                    }
+
+                    return {
+                        width: targetWidth,
+                        height: targetHeight,
+                        x: (containerWidth - targetWidth) / 2,
+                        y: (containerHeight - targetHeight) / 2
+                    };
+                }
+
+                if (objectFit === 'contain' || objectFit === 'cover') {
+                    const { width, height, x, y } = getObjectFitSize(objectFit === 'contain', box.width, box.height, image.width, image.height);
+                    newWidth = width;
+                    newHeight = height;
+                    this.ctx.drawImage(image, 0, 0, container.intrinsicWidth, container.intrinsicHeight, newX + x, newY + y, newWidth, newHeight);
+                } else {
+                    this.ctx.drawImage(image, 0, 0, container.intrinsicWidth, container.intrinsicHeight, box.left, box.top, box.width, box.height);
+                }
+                
                 this.ctx.restore();
             }
         };

This issue body was partially generated by patch-package.

@Oussama-El-Benney
Copy link

Thanks a lot, Actually this solved the object-fit problem because i changed directly in the node_modules.
But the the problem when i deployed on vercel that these changes aren't applied.
note : using Next js

@raphaelbadia
Copy link
Author

@Oussama-El-Benney you need to use patch-package with a postinstall script, so the changes are applied every time you (or vercel) does a postinstall

@Oussama-El-Benney
Copy link

Oussama-El-Benney commented Jan 9, 2024

@Oussama-El-Benney you need to use patch-package with a postinstall script, so the changes are applied every time you (or vercel) does a postinstall

thanks, i'll try this

Edit : it works, Thanks a lot

@the-didi
Copy link

every good work, make my code rotate,love from china!

@antoine10245
Copy link

could we get this merged?

@sansil
Copy link

sansil commented Mar 1, 2024

any chance to merge this? ty

@chenzhengduan
Copy link

Hi, I tried to change it like this, but it didn't take effect

@raphaelbadia
Copy link
Author

raphaelbadia commented Mar 21, 2024

Hi, I tried to change it like this, but it didn't take effect

try npmjs.com/package/html2canvas-pro, this supports object-fit

⚠️⚠️⚠️⚠️ possible scam alert ⚠️⚠️⚠️⚠️⚠️⚠️

I see that the commit history has been completely erased which is very shady.

https://github.com/yorickshan/html2canvas-pro/commits/main/

I strongly recommend anyone to ⚠️ AVOID ⚠️ using html2canvas-pro, we don't know what you changed, there could be a backdoor or something like that.

Please do a clean fork with commit history 🙏

@luskafaria
Copy link

Thanks @raphaelbadia 🙏🏻

@mmis1000 mmis1000 linked a pull request Nov 28, 2024 that will close this issue
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants