【问题标题】:Font style of text in svg not propagating to png on downloadsvg中文本的字体样式在下载时不会传播到png
【发布时间】:2020-11-26 23:59:57
【问题描述】:

我正在生成一个带有文本的 svg,使用 D3.js 供用户下载。

不幸的是,当下载 svg 时,应用到 svg 上的文本的字体系列在 svg 转换为画布然后下载为 png 时似乎不包括在内。

字体样式似乎丢失了。

有没有办法使用这个字体系列来构建 png?

要将 svg 下载为 png,我调整了答案 described here

这是我的过程:

首先,我创建 svg。

     await d3.xml(`img_templates/${template}_${dimensions}.svg`)
        .then(data => {
        
            divsvg.append(data.documentElement) //Append svg to DOM 
           
        }); 

然后,我将我的文本元素添加到 svg

 const quoteText = quoteGroup.append("text")
            .attr("class", "quote")
            .style("font-size", `15px`)
            .style("font-family", 'Merriweather')

Merriweather 是一个 Google 字体系列,我将其加载到 html 页面的头部,如下所示:

 <head>
    <link href="https://fonts.googleapis.com/css2?family=Merriweather&display=swap" rel="stylesheet"> 
    <link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,700;1,400&display=swap" rel="stylesheet"> <!--Another font I use-->
    <script src="d3.min.js"></script>
    <script src=genImage.js></script> <!--The js code to interact with the svg --> 
  </head>

下载时,我在 svg 上执行以下功能,

function downloadSVG(svgObj){
  
    var data = (new XMLSerializer()).serializeToString(svgObj);
     
    var DOMURL = window.URL || window.webkitURL || window;
    var img = new Image();
    var svgBlob = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
    var url = DOMURL.createObjectURL(svgBlob);
    
    img.onload = function () {
        var canvas = document.createElement("canvas");              
        canvas.width = this.width; 
        canvas.height = this.height; 
        var ctx = canvas.getContext("2d");

        ctx.drawImage(img, 0, 0);
        DOMURL.revokeObjectURL(url);
    
        var imgURI = canvas
            .toDataURL('image/png')
            .replace('image/png', 'image/octet-stream');
        // console.log(imgURI)
        triggerDownload(imgURI);
    };
    
    img.src = url;
}



function triggerDownload (imgURI) {
    var evt = new MouseEvent('click', {
      view: window,
      bubbles: false,
      cancelable: true
    });
  
    var a = document.createElement('a');
    a.setAttribute('download', 'MY_COOL_IMAGE.png');
    a.setAttribute('href', imgURI);
    a.setAttribute('target', '_blank');
  
    a.dispatchEvent(evt);
  }

当序列化为字符串时,svg 显示如下:

<svg xmlns="http://www.w3.org/2000/svg" width="484" height="484" viewBox="0 0 484 484" fill="none">

<g class="quoteGroup" transform="translate(42,100)">
<text class="quote" fill="#FFFFFF" style="font-size: 25px; font-family: Merriweather;"><tspan x="0">"I’m staying alone in Montauk at a</tspan><tspan x="0" dy="40px">friend’s house while he’s in Portugal</tspan><tspan x="0" dy="40px">(something about taxes and quality of</tspan><tspan x="0" dy="40px">life). After my morning coffee and</tspan><tspan x="0" dy="40px">power shake, it’s time to water the</tspan><tspan x="0" dy="40px">plants."</tspan></text>
</g>

<g class="headlineGroup" transform="translate(42,365)">
<text class="headline" font-size="15px" fill="#FFFFFF" style="font-family: Roboto; font-style: italic;"><tspan x="0">Stop Thinking of the Breakup of Big Tech as Punishment</tspan></text>
</g>

<g class="publisherGroup" transform="translate(42,430)">
<text class="publisher" font-size="15px" fill="#FFFFFF" style="font-family: Roboto; font-weight: bold;">Marker</text>
</g>

<g class="dateGroup" transform="translate(353,430)"><text class="date" font-size="15px" fill="#FFFFFF" style="font-family: Roboto; font-weight: bold;">Aug 04, 2020</text></g>

</svg>

据我所知,在字符串中正确指定了字体系列,但是当 svg 转换为画布然后转换为 png 时,它正在丢失。为什么会发生这种情况?

如果我可以提供任何其他信息,请告诉我。非常感谢任何帮助!

【问题讨论】:

  • 因为字体定义不在 SVG 中,它们在 HTML 文档中,BLOB 无法从那里读取它们。
  • 有道理,有没有一个地方可以放置字体定义以使 BLOB 可以访问它们?我也将字体下载为 .ttf 文件
  • 您可以尝试对它们进行 URL 编码(或 base64 编码)并将它们嵌入到 blob 中。

标签: javascript html css d3.js svg


【解决方案1】:

对于任何发现此问题的人,我都能解决。

感谢Longson先生的建议,我在this question找到了Kaiido的以下回答。

Kaiido 的 GFontToDataURI 方法运行良好。我将它合并到我的代码中,如下所示:

            GFontToDataURI("https://fonts.googleapis.com/css2?family=Merriweather&display=swap")
                .then(cssRules => {
                    let fontRules = cssRules.join('\n')
                    d3.select("svg").append('defs').append('style').attr('type', 'text/css').text(fontRules)
                    console.log("Added Merriweather")
                })
                .catch(reason => console.log(reason)) 
            
            GFontToDataURI("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,700;1,400&display=swap")
                .then(cssRules => {
                    let fontRules = cssRules.join('\n')
                    d3.select("svg").append('defs').append('style').attr('type', 'text/css').text(fontRules)
                    console.log("Added roboto")
                })
                .catch(reason => console.log(reason)) 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-07
    • 2021-11-08
    • 2022-01-24
    • 1970-01-01
    • 2013-02-20
    • 2017-05-30
    • 2011-11-11
    • 2022-12-16
    相关资源
    最近更新 更多