forked from tsayen/dom-to-image
-
Notifications
You must be signed in to change notification settings - Fork 123
Open
Description
I'm using the library (v.3.7.2) to create the image from HTML element and export it to PDF file.
const elementToPrint =
iframe.contentWindow.document.querySelector('.my-element-to-print');
const dataUrl = await domToImage.toJpeg(elementToPrint, {
quality: 1,
...other props,
});
Everithing works fine, I'm getting my beautiful PDF, but an error occurs:
Uncaught NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
at o.onload (VM49568 dom-to-image-more.min.js:2:3035)
o.onload @ dom-to-image-more.min.js:2
Error occurs in makeImage function when onLoad event is happening:
function makeImage(uri) {
if (uri === 'data:,') {
return Promise.resolve();
}
return new Promise(function (resolve, reject) {
// Create an SVG element to house the image
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
// and create the Image element to insert into that wrapper
const image = new Image();
if (domtoimage.impl.options.useCredentials) {
image.crossOrigin = 'use-credentials';
}
image.onload = function () {
// Cleanup: remove theimage from the document
document.body.removeChild(svg); // !!!! Error occurs here !!!!
if (window && window.requestAnimationFrame) {
// In order to work around a Firefox bug (webcompat/web-bugs#119834) we
// need to wait one extra frame before it's safe to read the image data.
window.requestAnimationFrame(function () {
resolve(image);
});
} else {
// If we don't have a window or requestAnimationFrame function proceed immediately.
resolve(image);
}
};
image.onerror = (error) => {
// Cleanup: remove the image from the document
document.body.removeChild(svg);
reject(error);
};
svg.appendChild(image);
image.src = uri;
// Add the SVG to the document body (invisible)
document.body.appendChild(svg);
});
}
I managed to get rid of the error by adding a patch to this function:
import domToImage from 'dom-to-image-more';
const patchedDomToImage = patchDomToImage(domToImage);
const dataUrl = await patchedDomToImage.toJpeg(elementToPrint, {
quality: 1,
...other props,
});
In patch function I added a simple check, if parentNode of 'svg' is document.body:
function patchDomToImage(domToImage: any) {
if (domToImage && !domToImage.patched) {
domToImage.impl.util.makeImage = (uri: string) => {
if (uri === 'data:,') {
return Promise.resolve();
}
return new Promise(function (resolve, reject) {
const svg = document.createElementNS(
'http://www.w3.org/2000/svg',
'svg',
);
const image = new Image();
if (domToImage.impl.options.useCredentials) {
image.crossOrigin = 'use-credentials';
}
image.onload = function () {
// If parent svg exists in document.body
// Remove it
if (svg.parentNode === document.body) {
document.body.removeChild(svg);
}
if (window?.requestAnimationFrame) {
window.requestAnimationFrame(function () {
resolve(image);
});
} else {
resolve(image);
}
};
image.onerror = error => {
// If parent svg exists in document.body
// Remove it
if (svg.parentNode === document.body) {
document.body.removeChild(svg);
}
reject(error);
};
svg.appendChild(image);
image.src = uri;
document.body.appendChild(svg);
});
};
domToImage.patched = true;
}
return domToImage;
}
Now everything works fine with no errors. I don't know the exact reason why the script doesn't find the SVG node, perhaps the garbage collector manages to delete it.
It would be interesting to hear your ideas about the reasons for this error.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels