bubkoo / html-to-image

āœ‚ļø Generates an image from a DOM node using HTML5 canvas and SVG.
MIT License
5.66k stars 524 forks source link

Load fonts from document.fonts #213

Open nihey opened 2 years ago

nihey commented 2 years ago

Hi there, html-to-image is great lib for us!

Expected Behavior

It would be good if it loaded fonts from documents.fonts too. Loading the fonts from document.fonts would solve this issue and give a more consistent result with the UI.

Currently, it appears that only the fonts that are on a @font-face in a <style> tag are loaded for the screenshot

Possible Solution

We can use document.fonts.entries() to iterate over all loaded fonts and use it to load the fonts in the same way it is done in CSS. It could possibly replace the currently adopted solution as fonts loaded through CSS appear on document.fonts too.

Additional Context

I'm working on a product that loads fonts directly into document.fonts, because we load fonts dynamically based on some user inputs. The fonts are rendered on the HTML without problems, but they just don't appear on the screenshot.

I've currently worked this out on our product by dynamically injecting the <style> element with the @font-face too. But I believe it would be good for this lib to support it directly too.

I would be willing to contribute.

Our UI

Screenshot from 2021-11-11 20-23-49

Screenshot (the text at the top is actually an image, so it appears in the same way)

videomatik-screenshot (21)

Expected Result

videomatik-screenshot (22)

vivcat[bot] commented 2 years ago

šŸ‘‹ @nihey

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.

jessejamesrich commented 2 years ago

+1.

hugh-maaskant commented 2 years ago

I seem to have the same issue. I use the Gothic A1 font which shows nice on the rendered HTML (in Chrome, Edge and Firefox on Windows 10) but not in the captured .png file. Everything else works great (transparency, colors, size) but the font is not picked up.

I am using a .Net Blazor wasm app to do the work, took me a while to get it working which was mostly due to my inexperience with Javascript, Node, and Webpack. I could mimimize the app and make it available as a public repo if this helps in the diagnosis, but I doubt it would as you would potentially suffer from the reverse problem: inexperience with .Net and Blazor ;-). Just let me know though

I have attached a screenshot that clearly demonstrates the problem:

Font-problem

hugh-maaskant commented 2 years ago

OK, after some more testing I found the following:

  1. Delaying the call to htmlToImage.toPng() in the hope that the fonts were not yet downloaded from fonts.google.com did not help. So it is not an issue of the font not yet being available.
  2. Installing the font on the local machine solved the problem. This is sufficient in my case, but obviously not in the general case

Hope this helps in the diagnosis!

noeRls commented 2 years ago

+1

eyeris-ovidiumiu commented 2 years ago

+1

noeRls commented 2 years ago

+1

luigimannoni commented 2 years ago

Someone kill this bot, please. Bump

luigimannoni commented 2 years ago

Bump

noeRls commented 2 years ago

+1

noeRls commented 2 years ago

+1

noeRls commented 2 years ago

+1

AntonioRedondo commented 1 year ago

It would be great to support fonts loaded with the documents.fonts API. html2canvas supports this feature. But I prefer html-to-image as it's faster and renders text better.

Meanwhile, a way to load fonts asynchronously and use them with html-to-image is:


const urlToFontFile = 'something';
const fontName = 'something';

const response = await fetch(urlToFontFile);
const fontArrayBuffer = await response.arrayBuffer();

const style = document.createElement('style');
style.textContent = `
  @font-face {
    font-family: '${fontName}';
    src: url(${fontArrayBuffer});
  }
`;
document.head.appendChild(style);

const nodeWithCustomFontFace = document.createElement('div');
nodeWithCustomFontFace.style.fontFace = fontName;
nodeWithCustomFontFace.textContent = 'I look pretty';

const myCanvas = await htmlToImage.toCanvas(nodeWithCustomFontFace); // It should render with the custom font
swaree commented 1 year ago

+1

webpig commented 1 year ago

It would be great to support fonts loaded with the documents.fonts API. html2canvas supports this feature. But I prefer html-to-image as it's faster and renders text better.

Meanwhile, a way to load fonts asynchronously and use them with html-to-image is:

const urlToFontFile = 'something';
const fontName = 'something';

const response = await fetch(urlToFontFile);
const fontArrayBuffer = await response.arrayBuffer();

const style = document.createElement('style');
style.textContent = `
  @font-face {
    font-family: '${fontName}';
    src: url(${fontArrayBuffer});
  }
`;
document.head.appendChild(style);

const nodeWithCustomFontFace = document.createElement('div');
nodeWithCustomFontFace.style.fontFace = fontName;
nodeWithCustomFontFace.textContent = 'I look pretty';

const myCanvas = await htmlToImage.toCanvas(nodeWithCustomFontFace); // It should render with the custom font

How to handle local fonts? Fetch local fonts file is not work.

davinun99 commented 1 year ago

+1

PattyRich commented 1 year ago

Specifically for me I fixed this issue by turning off the chrome extension Dark Reader. It was affecting how the module was grabbing styleSheets.

simonsankar commented 9 months ago

+100

suryasanchez commented 8 months ago

I was able to fix my case with https://github.com/bubkoo/html-to-image/issues/207

mrold commented 7 months ago

+1

GlebBigma commented 6 months ago

+1

ashiq-prospero commented 4 months ago

I am loading google fonts dynamically and its an editor where I want to take the screenshot, so please add the support for document.fonts.

mrold commented 4 months ago

@ashiq-prospero If you can obtain the list of fonts, I suggest customizing the generation of fontEmbedCSS.here