qq15725 / modern-screenshot

📸 Quickly generate image from DOM node using HTML5 canvas and SVG
https://toolpkg.com/html-to-image
MIT License
504 stars 36 forks source link

新必应聊天导出后,大部分引用的链接由一行变成两行 #8

Open gantrol opened 1 year ago

gantrol commented 1 year ago

必应聊天分享与保存项目引用了你这个库,效果很不错的。

只是目前还有一点疑问,怎么才能把变成文本两行的引用调整成一行?

效果图

image

原网页

image

引用部分的css

引用的css2

qq15725 commented 1 year ago

我似乎无法提交 bing chat 的加入等候列表,可以提供个最小的复现片段吗 😄

https://codepen.io/qq15725/pen/poOoQZz

qq15725 commented 1 year ago
image

字宽 67px

image

字宽 65px

貌似是这 2px 导致的,不知道是不是 font-size 或者 font-family 截图时取值的问题

gantrol commented 1 year ago

我似乎无法提交 bing chat 的加入等候列表,可以提供个最小的复现片段吗 😄

https://codepen.io/qq15725/pen/poOoQZz

分析了下,不知道是不是字体的问题,链接的字在原网页上偏细,而在codepen复现的时候,字跟输出的图片一样粗。

原网页前端比较复杂,个人没找出为何字那么细的原因,抱歉。

qq15725 commented 1 year ago
  1. 可能需要查看 var(--cib-font-text) 和对应字体值的 @font-face css 定义部分(写法)
  2. 尝试检查 data:image/svg+xml; 请求中是否正常内嵌该字体,类似 image

或者等我申请个 Bing Chat 再试试 😄

gantrol commented 1 year ago
  1. 尝试检查 data:image/svg+xml; 请求中是否正常内嵌该字体,类似

disable cache后,仅有一个下载svg的请求

  1. 可能需要查看 var(--cib-font-text) 和对应字体值的 @font-face css 定义部分(写法)
var(--cib-font-text): -apple-system, Roboto, SegoeUI, "Segoe UI", "Helvetica Neue", Helvetica, "Microsoft YaHei", "Meiryo UI", Meiryo, Arial Unicode MS, sans-serif

@font-face {
font-family: 'Roboto Light';
src: url(/sa/simg/Roboto_Light.woff2) format('woff2');
unicode-range: U+0-FF,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2212,U+2215
}

@font-face {
font-family: 'Roboto';
src: url(/sa/simg/Roboto_Regular.woff2) format('woff2');
unicode-range: U+0-FF,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2212,U+2215
}

@font-face {
font-family: 'Roboto Semibold';
src: url(/sa/simg/Roboto_Semibold.woff2) format('woff2');
unicode-range: U+0-FF,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2212,U+2215
}

@font-face {
font-family: 'Roboto';
font-weight: 200;
src: url(/sa/simg/Roboto_Light.woff2) format('woff2');
unicode-range: U+0-FF,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2212,U+2215
}

@font-face {
font-family: 'Roboto';
font-weight: 300;
src: url(/sa/simg/Roboto_Light.woff2) format('woff2');
unicode-range: U+0-FF,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2212,U+2215
}

@font-face {
font-family: 'Roboto';
font-weight: 600;
src: url(/sa/simg/Roboto_Semibold.woff2) format('woff2');
unicode-range: U+0-FF,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2212,U+2215
}

@font-face {
font-family: 'Roboto';
font-weight: 700;
src: url(/sa/simg/Roboto_Semibold.woff2) format('woff2');
unicode-range: U+0-FF,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2212,U+2215
}
qq15725 commented 1 year ago

感谢,这应该是我的一个 bug,当 font-family 出现多个字体时会被过滤掉不处理内嵌 font

可以尝试 modern-screenshot@4.3.4 如果还存在这个问题可以再打开 issue

p: Bing Chat 在申请了 😄

gantrol commented 1 year ago

问题还是有,不过可能不是这个库的缺陷。问题与font-weight: 500;相关

image

我将引用部分的font-weight改为400,导出居然没有问题(两个版本都一样)

image

qq15725 commented 1 year ago

😂 那还是等晚些申请通过了,我自己试试确认下问题

ha1fstack commented 1 year ago

I have similar problem too, it also appears in html-to-image package.

Sometimes width of text element and width of container holding the text doesn't match and it causes text to line wrap. In my case, it works fine on desktop browsers but breaks on mobile devices. Some devices are fine, some are not.

Added whitespace nowrap for temporary fix.

qq15725 commented 1 year ago

初步判断应该是 svg+xml 的字体渲染和源 html 内的不一致

可能是 opentype 的 gsub 表部分逻辑浏览器渲染不一致导致的

https://learn.microsoft.com/en-us/typography/opentype/spec/gsub

此处发现一个相关的测试用例

https://github.com/qq15725/modern-screenshot/blob/v4.4.2/test/fixtures/dom.comment.html

在 4.4.1 版本(未移除注释)下能复现

jsbmg commented 1 year ago

Any other solutions to this? I tried white-space: nowrap. While this does prevent the line wrapping issue, it is necessary, for my case, to have the text wrap.

qq15725 commented 1 year ago

If someone can provide a copy of the code, it can help me solve this problem

Playground link

gantrol commented 1 year ago

If someone can provide a copy of the code, it can help me solve this problem

Playground link

必应这个网站一堆 shawdowdom,我个人不知道怎么下载。

如果你的 Bing 账号还没通过,那可以试试这个方法:

前两周是秒通过的,不知道现在怎样

jsbmg commented 1 year ago

If someone can provide a copy of the code, it can help me solve this problem

Playground link

I'm trying to replicate the issue, but I'm unable to get modern-screenshot to load the custom font: Playground

Not sure how to get the font "Montserrat" loaded in this playground example. I'm able to do it on my own code, it's just not working here (I'm not very familiar with Vue). The problem only occurs when I'm using a custom font. If I disable fonts (like it is here), there is no problem.

qq15725 commented 1 year ago

It seems normal Codepen html playground

jsbmg commented 1 year ago

Thanks. I can't reproduce the exact problem at the moment, but it might have something to do with Firefox. The bottom of the text is cut off in Firefox, but displays correctly on Chrome. If I disable the custom font, it renders correctly in Firefox. Both cases work on Chrome.

Still not the exact problem I was having before, but that problem was also fixed by disabling Montserrat and going with browser default. I'll try and come up with a better example when I have some more time.

Codepen

Picture of result in Firefox (note the text is cutoff at the bottom. It's not cutoff in the original rendering). It also looks like the font is incorrectly rendered, or rendered at a different weight in Firefox:

2023-04-10-231600_471x261_scrot

Flourad commented 11 months ago

it

您好 打扰了

image

我这个截图之后,也是这个换行错乱了,请问是什么原因呀?

emmanuelpignat commented 3 months ago

Hi @qq15725 and thanks for your amazing work !

I came across this problem which was coming with several font families, sizes, and weights. It occurs to me that it might be because of very small approximations which makes the text slightly bigger, overflow and being wrapped. I tried to make all font sizes smaller when rendering by only 0.01% and as far as I tested, all my problems are gone.

To do this, I just added the following code in function copyCssStyles :

const fs = style.get('font-size')
if(fs){
    const value = splitValueAndUnit(fs[0])
    style.set('font-size', [value.value * 0.9999 + value.unit, ''])
}

I'll tell you if I see the problem appearing again.

kvindascr commented 2 months ago

I was facing this issue and solved it inspired on @emmanuelpignat solution. In my case, I have guaranteed that all the CSS font units are in pixels due to the way the theme is structured, so it's easier to solve the issue.

I'm using the onCloneNode listener, to update the cloned node and reduce the font-sizes by 1px.

const imageDataUrl = await domToDataUrl(elemRef.current, {
    //... otherOptionsHere
    onCloneNode: (node) => {
        normalizeDomNodeForSvgScreenshot(node as HTMLElement);
    },
});

export function splitCssValueAndUnit(cssValue: string) {
    const regex = /^(-?\d*\.?\d+)([a-zA-Z%]*)$/;
    const match = cssValue.match(regex);

    if (match) {
        const numericValue = parseFloat(match[1]);
        const unit = match[2];
        return { value: numericValue, unit: unit };
    } else {
        throw new Error('Invalid CSS value format');
    }
}

export const normalizeDomNodeForSvgScreenshot = (node: HTMLElement) => {
    const fontSize = node.style.fontSize;
    if (fontSize) {
        try {
            const { value, unit } = splitCssValueAndUnit(fontSize);
            node.style.fontSize = `${value - 1}${unit}`; // Reducing font-size by 1px
        } catch (err) {
            // Ignore
        }
    }
    for (const childNode of node.children) {
        normalizeDomNodeForSvgScreenshot(childNode as HTMLElement);
    }
};      

I hope this can be of help for some of the folks dealing with this issue.

As a side comment, the solution from @emmanuelpignat and multiplying the font size by 0.9999 didn't work for me, at least it didn't decrease the font-size enough to prevent the texts from wrapping up. My hypothesis is that when applying that operation to pixel units, the font is not reduced enough, maybe if using em or rem units it may work differently.