Skip to content

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

Open
@raphaelbadia

Description

@raphaelbadia

Hi! 👋

Firstly, thanks for your work on this project! 🙂

Today I used patch-package to patch [email protected] 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions