bubkoo / html-to-image

✂️ Generates an image from a DOM node using HTML5 canvas and SVG.
MIT License
5.41k stars 505 forks source link

Ui Freezing #347

Open rubendub17 opened 1 year ago

rubendub17 commented 1 year ago

Hello, I'm using this library to create pdf in an angular app, but the process of converting to an SVG freezes the UI. The function ToSvg returns a promise, but even without using "await", the UI gets stuck.

Is there any way off doing this operation without freazing main Thread ? I tried WebWorkers but they cant access DOM so it gives an error while cloning.

vivcat[bot] commented 1 year ago

👋 @rubendub17

Thanks for opening your first issue here! If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. To help make it easier for us to investigate your issue, please follow the contributing guidelines.

We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can.

mareksobieraj commented 1 year ago

+1

LiuJi-Jim commented 1 year ago

+1 Is that possible to run html-to-image in WebWorker?

mareksobieraj commented 1 year ago

@LiuJi-Jim For now, it's technically impossible because of web worker limitation. I've noticed that under the hood library clones each html element, and this operation is not cheap, it's time consuming especially when your DOM is huge. I suggest to glance your elements and consider how to improve it. For instance, we were rendering a lot of svg elements dynamically, it was worth to render them at the end as an image, which speed up html-to-image performance a lot. It's a simple relation, the less complex DOM, the faster execution. Good luck.

nextend commented 1 year ago

Here is what worked for me:

return new Promise((resolve, reject) => {
    requestAnimationFrame(() => {
        requestAnimationFrame(() => {
            htmlToImage.toPng(...)
        })
        .then(resolve)
        .catch(reject);
    });
});
Sleeper9 commented 10 months ago

+1 same here, I'd also add that applying computed styles for every cloned node is part of the problem. So if you have 100-200 HTML nodes within the root node, it'll apply 300+ styles individually (based on my debug sessions)

tx-ares commented 3 months ago

I faced this problem while implementing html-to-image call from within a Mat Dialog. Luckily Angular has Zone.js that can help for such processes. The problem is that Angular is running a whole bunch of unnecessary change detection while html-to-image is creating the screenshot image.

Using Angular Dev tools profiler you can see that nearly 800 changes are being detected during the screenshotting call:

Untitled

Here's what worked for me:

Inject and use ngZone to tell Angular to ignore changes detection while html-to-image is being ran. image

And voila, profiler's change count returns to normal, ( And the screen isn't hanging while the screenshot is happening. )

Untitled

This was helpful learning more about from Angular's documentation: https://angular.io/guide/change-detection-zone-pollution

radiantone commented 3 days ago

Also having this problem