[FIX] web_editor: make to_inline with html2canvas fast
In mass_mailing, when there is an element with a background image, the method html2canvas is used. On a Mac M1, rendering that snippet takes ±700ms per element that goes into html2canvas. The reason is that html2canvas clone all the document of the node that is passed to html2canvas. This is the document of the mass mailing iframe (for instance including the snippet menu). As a rendering is called at each input change in the editable (eg. editor blur, adding a snipet, ...), the main thread will be blocked more than 700ms each time the input change. The reason it is slow is because html2canvas is cloning the whole document, in order to properly get the style of the targeted element. Because the element style is already inlined by the to_inline, this is not necessary to clone the whole document. In order to make html2canvas instantaneous without changing the lib source code, the solution is to render from another iframe that contain only the element to render. task-3100165 X-original-commit: 8ea22ea04e4d7108ba6920fed3e1898df28a53d8 Part-of: odoo/odoo#112908
This commit is contained in:
@@ -640,7 +640,18 @@ async function toInline($editable, cssRules, $iframe) {
|
||||
async function flattenBackgroundImages(editable) {
|
||||
for (const backgroundImage of editable.querySelectorAll('*[style*=background-image]')) {
|
||||
if (backgroundImage.parentElement) { // If the image was nested, we removed it already.
|
||||
const canvas = await html2canvas(backgroundImage, { scale: 1 });
|
||||
const iframe = document.createElement('iframe');
|
||||
const style = getComputedStyle(backgroundImage);
|
||||
const clonedBackground = backgroundImage.cloneNode(true);
|
||||
clonedBackground.style.height = style['height'];
|
||||
clonedBackground.style.width = style['width'];
|
||||
iframe.style.height = style['height'];
|
||||
iframe.style.width = style['width'];
|
||||
backgroundImage.after(iframe);
|
||||
iframe.contentDocument.body.append(clonedBackground);
|
||||
iframe.contentDocument.body.style.margin = 0;
|
||||
|
||||
const canvas = await html2canvas(clonedBackground, { scale: 1 });
|
||||
const image = document.createElement('img');
|
||||
image.setAttribute('src', canvas.toDataURL('png'));
|
||||
image.setAttribute('width', canvas.getAttribute('width'));
|
||||
@@ -648,12 +659,11 @@ async function flattenBackgroundImages(editable) {
|
||||
image.style.setProperty('margin', 0);
|
||||
image.style.setProperty('display', 'block'); // Ensure no added vertical space.
|
||||
// Clean up the original element.
|
||||
for (const child of [...backgroundImage.childNodes]) {
|
||||
child.remove();
|
||||
}
|
||||
backgroundImage.replaceChildren();
|
||||
backgroundImage.style.setProperty('padding', 0);
|
||||
backgroundImage.style.removeProperty('background-image');
|
||||
backgroundImage.prepend(image); // Add the image to the original element.
|
||||
iframe.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user