【问题标题】:Export SVG as Image with custom Icon Font使用自定义图标字体将 SVG 导出为图像
【发布时间】:2021-09-05 05:42:00
【问题描述】:

希望有人能帮我解决这个问题:

目标是将内联 SVG 保存为 PNG 图像。

问题在于,上述 SVG 具有包含 webfont 图标的 foreignObject 元素(来自 Fontawesome 以及使用 Icomoon 创建的自定义图标)。

为了将 SVG 导出为 PNG,我使用了 Save inline SVG as JPEG/PNG/SVG 中描述的方法。 为了获得 SVG 的正确视图,我将所有计算的样式复制到 svg 元素的副本中作为内联样式(复制以不污染原始样式)。但是,由于字体图标仅作为 ::before 元素嵌入 HTML 中,并且这些元素不能用作内联样式,因此在导出 SVG 时它们被忽略了。 我的解决方法是将图标字形的 unicode 作为 innerHTML 标记的 i 并让 SVG 像普通文本一样处理它。

这里的问题是导出的图像无法访问包含图标的字体。所以我尝试使用Including fonts when converting SVG to PNG 中描述的解决方法,并将图标字体的base64 编码版本嵌入到svgs defs --> style 标签内。这种方法的第一个问题是我不能直接使用btoa(),因为我添加了图标unicode字符,但为此使用了MDN Web Docs中描述的第一个解决方案。

但在这一切之后,我仍然无法让图标显示在导出的图像上,而且我没有想法......

以下是 SVG 的 Web 版本的外观:

导出的版本如下所示:

这是导出的代码:

download(selector: string, name: string): void {
    const svg = <HTMLElement>document.querySelector(selector + ' svg')
    const svgCopy = svg.cloneNode(true) as HTMLElement

    this.computedToInline(svg, svgCopy)

    const canvas = <HTMLCanvasElement>document.querySelector('canvas')

    canvas.width = svg.getBoundingClientRect().width
    canvas.height = svg.getBoundingClientRect().height
    const ctx = canvas.getContext('2d')
    if (!ctx) return

    const data = new XMLSerializer().serializeToString(svgCopy)

    const image = new Image()
    const encodedData = btoa(unescape(encodeURIComponent(data)))
    const url = 'data:image/svg+xml;base64,' + encodedData

    image.onload = () => {
        ctx.drawImage(image, 0, 0)

        window.URL.revokeObjectURL(url)

        const imageURI = canvas
            .toDataURL('image/png')
            .replace('image/png', 'image/octet-stream')

        this.triggerDownload(imageURI, name)
    }

    image.src = url
}

computedToInline(element: HTMLElement, elementCopy: HTMLElement): void {
    if (element.hasChildNodes()) {
        for (let i = 0; i < element.children.length; i++) {
            this.computedToInline(
                element.children[i] as HTMLElement,
                elementCopy.children[i] as HTMLElement
            )
        }
    }

    const computedStyles = getComputedStyle(element)
    for (let i = 0; i < computedStyles.length; i++) {
        const style = computedStyles[i]
        elementCopy.style.setProperty(style, computedStyles.getPropertyValue(style))
    }

    if (element.classList.contains('icon')) {
        elementCopy.style.font = '900 14px "Custom Icon Font"'
        // the text ICON is just added for visualisation purpose
        elementCopy.innerHTML = 'ICON\ue900'
    }
}

SVG 中的字体是这样嵌入的: 嵌入在 SVG 中的 Base64 编码字体

【问题讨论】:

    标签: javascript typescript svg fonts export


    【解决方案1】:

    不确定您从另一个答案中遵循的方法。 我之前使用了 saveSvgAsPng npm 包,它就像魅力一样。

    1. 安装包
        npm install save-svg-as-png
    
    1. 通过要导出为图像的元素的 hmtl id 使用它:
        saveSvgAsPng(document.getElementById("IdOfHTMLDiv"), "ImageName.png");
    
    

    您也可以导出为svgAsDataUrisvgAsPngUri

    要添加字体,您可以使用类似的选项

    const imageOptions = {
          fonts: [
            {
              url: 'https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu72xKKTU1Kvnz.woff2',
              format: 'application/font-woff2',
              text: "@font-face {font-family: 'Roboto';  font-style: normal;  font-weight: 400; src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu72xKKTU1Kvnz.woff2) format('woff2');  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;}",
            },
            {
              url: 'https://fonts.gstatic.com/s/sharetechmono/v9/J7aHnp1uDWRBEqV98dVQztYldFcLowEFA87Heg.woff2',
              format: 'application/font-woff2',
              text: "@font-face {font-family: 'Share Tech Mono'; font-style: normal; font-weight: 400; src: local('Share Tech Mono'), local('ShareTechMono-Regular'), url(https://fonts.gstatic.com/s/sharetechmono/v9/J7aHnp1uDWRBEqV98dVQztYldFcLowEFA87Heg.woff2) format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }",
            }
          ],
        };
    
    svgAsPngUri(document.getElementById("diagram"), imageOptions).then(uri => ...)
    

    更多详情请参考Github Page

    【讨论】:

      猜你喜欢
      • 2016-09-02
      • 2023-03-07
      • 2013-07-01
      • 1970-01-01
      • 2023-04-05
      • 2015-11-21
      • 1970-01-01
      • 2019-11-05
      • 2020-11-21
      相关资源
      最近更新 更多