Skip to content
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

Blank Image in Safari #461

Open
himanshupatil363 opened this issue Apr 12, 2024 · 10 comments
Open

Blank Image in Safari #461

himanshupatil363 opened this issue Apr 12, 2024 · 10 comments
Labels

Comments

@himanshupatil363
Copy link

himanshupatil363 commented Apr 12, 2024

We are basically trying to take screenshots of a div which has images as it's child the output we are getting has blank spaces instead of images this works fine on chrome but safari has this issue

@vivcat
Copy link
Contributor

vivcat bot commented Apr 12, 2024

👋 @himanshupatil363

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.

@JokeShaco
Copy link

I also encountered this problem

@frong123nk
Copy link

It seems to be a Safari bug that doesn't load the canvas immediately when the web page is rendered.
I tried to fork the code and fix it by setting a timeout when loading an image in util.ts within the createImage function.
from
img.onload = () => resolve(img)
to

 img.onload = () => {
      setTimeout(function () {
        resolve(img);
      }, 300);
    };

@jagabs
Copy link

jagabs commented Jun 8, 2024

img.onload = () => {
setTimeout(function () {
resolve(img);
}, 300);
};

this works in mac safari but doesnt work in ios safari tho after 2-3 times the img does show

@frong123nk
Copy link

frong123nk commented Jun 10, 2024

img.onload = () => {
setTimeout(function () {
resolve(img);
}, 300);
};

this works in mac safari but doesnt work in ios safari tho after 2-3 times the img does show

Another way you can try is to loop the toCanvas function, but it's not the best practice because you don't know how many times to show the image.

export async function convertHtmlToCanvas(
  targetElement: HTMLElement,
  countReRender: number = 0,
): Promise<HTMLCanvasElement> {
  let canvas: any;
    for (let i = 0; i < countReRender; i++) {
      canvas = await toCanvas(targetElement);
    }
  return canvas;
}

@Rabithua
Copy link

In the same situation, the problems encountered in Safari are a headache,

@Sebas3245
Copy link

¿Has anyone found a better solution than the loop solution?

@DMTaswebdevelopment
Copy link

DMTaswebdevelopment commented Jul 3, 2024

Here's how I fixed mine in Safari. I added delay using modern-screenshot: https://github.com/qq15725/modern-screenshot/tree/main

Which also came from html-to-image.

``
if (!isSafari) {
dataURL = await htmlToImage.toPng(imageElement);
} else {
//put a timer on the domToCanvas for 500ms to make sure the image is loaded
dataURL = await domToCanvas(imageElement, {
delay: 500,
debug: true,
}).then((canvas) => {
dataURL = canvas.toDataURL("image/png");
return dataURL;
});
}

@nyeoni
Copy link

nyeoni commented Aug 4, 2024

@DMTaswebdevelopment There is no delay option.

@RonaldR
Copy link

RonaldR commented Sep 3, 2024

I used patch-package to patch [email protected] for the project I'm working on.

Here is the diff that solved my problem:

diff --git a/node_modules/html-to-image/es/index.js b/node_modules/html-to-image/es/index.js
index 0eda938..768f239 100644
--- a/node_modules/html-to-image/es/index.js
+++ b/node_modules/html-to-image/es/index.js
@@ -16,6 +16,10 @@ export async function toCanvas(node, options = {}) {
     const { width, height } = getImageSize(node, options);
     const svg = await toSvg(node, options);
     const img = await createImage(svg);
+    const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
+    if (isSafari) {
+        await new Promise(resolve => setTimeout(resolve, 1000));
+    }
     const canvas = document.createElement('canvas');
     const context = canvas.getContext('2d');
     const ratio = options.pixelRatio || getPixelRatio();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

9 participants