Skip to content

Commit 1ee2e7f

Browse files
Daz2345Darren Impey
and
Darren Impey
authored
fix: Large Dom sizes failing to be drawn correctly into canvas when exporting to PNG (#197)
When context.drawImage is called within the toCanvas method, we are able to go over the maximum limits of the browser inbuilt canvas object. When this happens draw commands within context.drawImage are ignored resulting in missing parts of the image. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size for details. This adds a checkCanvasDimensions function to ensure that the image is appropriately scaled before being drawn and a susbsequent options.skipAutoScale if a library user wishes to turn this default functionality off. Co-authored-by: Darren Impey <[email protected]>
1 parent dfe1707 commit 1ee2e7f

File tree

3 files changed

+39
-0
lines changed

3 files changed

+39
-0
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,14 @@ html2Image.toSVG(element1, { fontEmbedCss });
268268
html2Image.toSVG(element2, { fontEmbedCss });
269269
```
270270

271+
### skipAutoScale
272+
273+
When supplied, the library will skip the process of scaling extra large doms into the canvas object.
274+
You may experience loss of parts of the image if set to `true` and you are exporting a very large image.
275+
276+
Defaults to `false`
277+
278+
271279
## Browsers
272280

273281
Only standard lib is currently used, but make sure your browser supports:

src/index.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,29 @@ export async function toSvg<T extends HTMLElement>(
3434
.then((clonedNode) => nodeToDataURL(clonedNode, width, height))
3535
}
3636

37+
const dimensionCanvasLimit = 16384; // as per https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size
38+
39+
function checkCanvasDimensions(canvas: HTMLCanvasElement) {
40+
if (canvas.width > dimensionCanvasLimit || canvas.height > dimensionCanvasLimit) {
41+
if (canvas.width > dimensionCanvasLimit && canvas.height > dimensionCanvasLimit) {
42+
if (canvas.width > canvas.height) {
43+
canvas.height = canvas.height * (dimensionCanvasLimit / canvas.width);
44+
canvas.width = dimensionCanvasLimit;
45+
} else {
46+
canvas.width = canvas.width * (dimensionCanvasLimit / canvas.height);
47+
canvas.height = dimensionCanvasLimit;
48+
}
49+
} else {
50+
if (canvas.width > dimensionCanvasLimit) {
51+
canvas.height = canvas.height * (dimensionCanvasLimit / canvas.width);
52+
canvas.width = dimensionCanvasLimit;
53+
} else {
54+
canvas.width = canvas.width * (dimensionCanvasLimit / canvas.height);
55+
canvas.height = dimensionCanvasLimit;
56+
}
57+
}
58+
}
59+
}
3760
export async function toCanvas<T extends HTMLElement>(
3861
node: T,
3962
options: Options = {},
@@ -51,6 +74,10 @@ export async function toCanvas<T extends HTMLElement>(
5174

5275
canvas.width = canvasWidth * ratio
5376
canvas.height = canvasHeight * ratio
77+
78+
if(!options.skipAutoScale) {
79+
checkCanvasDimensions(canvas);
80+
}
5481
canvas.style.width = `${canvasWidth}`
5582
canvas.style.height = `${canvasHeight}`
5683

src/options.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,8 @@ export interface Options {
7171
* create embed CSS for use across multiple calls to library functions.
7272
*/
7373
fontEmbedCSS?: string
74+
/**
75+
* A boolean to turn off auto scaling for truly massive images..
76+
*/
77+
skipAutoScale?: boolean
7478
}

0 commit comments

Comments
 (0)