-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Image filled even div set to object-fit: cover; #1064
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
Comments
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:
|
Take LanderBeeuwsaert's solution (by downloading html2canvas.js so you can edit its code like they did) and replace
with
That should get you your desired results. It worked for me, at least. |
Any update on this? |
@LanderBeeuwsaert muchas gracias funciono perfecto , deberian agregarlo a la master es un muy buen aporte |
@niklasvh Seems you've been updating the project. |
@LanderBeeuwsaert where do i suppose to implement this hack of yours? |
@SamuraiPetrus |
Use version 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'); |
I cannot install the alpha build and patch-package isn't working for me. Suitable workaround for my situation is to just use background images. |
Where should i need to paste this code? |
After a bit of fiddling, I managed to get it to work for my purposes in the current version.
Search for the first few lines in the non-minified file. Thanks to @LanderBeeuwsaert for the base code. |
@canoncarlson my pleasure, thanks for the update. We'll integrate it and be able to update in the coming weeks because of this. |
I've managed to get it working also, change CanvasRenderer.prototype.renderReplacedElement in node_modules/html2canvas/dist/html2canvas.js around line 6274, I'm using RC 5 version, it is basically the same code as @canoncarlson, just to confirm that object-fit cover is working with this modification CanvasRenderer.prototype.renderReplacedElement = function (container, curves, image) {
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();
let newWidth;
let newHeight;
let newX = box.left;
let newY = box.top;
if(container.intrinsicWidth / box.width < container.intrinsicHeight / box.height) {
newWidth = box.width;
newHeight = container.intrinsicHeight * (box.width / container.intrinsicWidth);
newY = box.top + (box.height - newHeight) / 2;
} else {
newWidth = container.intrinsicWidth * (box.height / container.intrinsicHeight);
newHeight = box.height;
newX = box.left + (box.width - newWidth) / 2;
}
this.ctx.drawImage(image, 0, 0, container.intrinsicWidth, container.intrinsicHeight, newX, newY, newWidth, newHeight);
this.ctx.restore();
}
}; Thanks to @LanderBeeuwsaert for initial solution, and hope this fix end up in main version soon. |
Any updates on the issue? |
For someone who are hesitated to override files in |
Where should i need to paste this code? I don't find any non-minified file |
@Kamlesh-62 if you have installed this module in
|
Why did it change without any changes, the version number is 1.4.1 |
[fix] object-fit missing of html2canvas (niklasvh/html2canvas#1064)
For those who don't bother to patch the package, here's a hack based on plavet's solution. Just create a patched canvas and pass it to html2canvas: const root = document.body
// we need the scale to manually resize the canvas as well as passing it to html2canvas
const scale = window.devicePixelRatio
const canvas = document.createElement("canvas")
canvas.width = root.offsetWidth * scale
canvas.height = root.offsetHeight * scale
const ctx = canvas.getContext("2d")
const originalDrawImage = ctx.drawImage
ctx.drawImage = function (image, sx, sy, sw, sh, dx, dy, dw, dh) {
if (image instanceof HTMLImageElement) {
if (sw / dw < sh / dh) {
const _dh = dh
dh = sh * (dw / sw)
dy = dy + (_dh - dh) / 2
} else {
const _dw = dw
dw = sw * (dh / sh)
dx = dx + (_dw - dw) / 2
}
}
return originalDrawImage.call(ctx, image, sx, sy, sw, sh, dx, dy, dw, dh)
}
await html2canvas(root, {
canvas,
scale,
})
Edit: this applies |
I think there are a mistake in |
@dimitrycastex actually the original code works for There seems no simple patch or hack that works for both. Using a fork like in #2904 would be better. |
ahhh finally something that worked! |
Thank you for this. I took the liberty and modified it to handle the properties set on the original image. This is a verry hacky way to do it I guess but it works for my project. const root = document.body;
const customCanvas = document.createElement('canvas');
const scale = window.devicePixelRatio;
customCanvas.width = 1920 * scale;
customCanvas.height = 1080 * scale;
const ctx = customCanvas.getContext('2d');
const originalDrawImage = ctx.drawImage;
const images: { [key: string]: HTMLImageElement } = Array.from(root.getElementsByTagName('img')).reduce(
(map, img) => {
map[img.src] = img;
return map;
},
{} as { [key: string]: HTMLImageElement },
);
ctx.drawImage = function (image, sx, sy, sw, sh, dx, dy, dw, dh) {
if (image instanceof HTMLImageElement) {
const objectFit = images[image.src].style.objectFit || 'fill'; // Default to 'fill'
const objectPosition = images[image.src].style.objectPosition || 'center center'; // Default to 'center center'
sh = image.height;
sw = image.width;
const sourceRatio = sw / sh;
const destinationRatio = dw / dh;
// Parse objectPosition to determine alignment
let [horizontalPosition, verticalPosition] = objectPosition.split(' ');
if (!verticalPosition) {
// If only one value is provided, use it for both directions
verticalPosition = horizontalPosition;
}
// Adjust source dimensions and positions based on object-fit
switch (objectFit) {
case 'cover':
if (sourceRatio > destinationRatio) {
const newSw = sh * destinationRatio;
let offsetX = (sw - newSw) / 2; // Default center
if (horizontalPosition === 'left') offsetX = 0;
if (horizontalPosition === 'right') offsetX = sw - newSw;
sx += offsetX;
sw = newSw;
} else {
const newSh = sw / destinationRatio;
let offsetY = (sh - newSh) / 2; // Default center
if (verticalPosition === 'top') offsetY = 0;
if (verticalPosition === 'bottom') offsetY = sh - newSh;
sy += offsetY;
sh = newSh;
}
break;
case 'contain':
if (sourceRatio > destinationRatio) {
const newDh = dw / sourceRatio;
let offsetY = (dh - newDh) / 2; // Default center
if (verticalPosition === 'top') offsetY = 0;
if (verticalPosition === 'bottom') offsetY = dh - newDh;
dy += offsetY;
dh = newDh;
} else {
const newDw = dh * sourceRatio;
let offsetX = (dw - newDw) / 2; // Default center
if (horizontalPosition === 'left') offsetX = 0;
if (horizontalPosition === 'right') offsetX = dw - newDw;
dx += offsetX;
dw = newDw;
}
break;
case 'fill':
// No adjustments needed for object-position
break;
// Implement other object-fit values if needed
}
}
return originalDrawImage.call(ctx, image, sx, sy, sw, sh, dx, dy, dw, dh);
};
const canvas = await html2canvas(root, {
canvas: customCanvas,
windowHeight: 1080,
windowWidth: 1920,
}); |
http://imgur.com/3Zl6oRA | Pic 1
http://imgur.com/Wr006qF | Pic 2
Pic 1 is the div i want to capture, after it captured the image change its size *Pic 2.
Anyone could fix this ?
The text was updated successfully, but these errors were encountered: