简体   繁体   English

svg 中文本的字体样式不会在下载时传播到 png

[英]Font style of text in svg not propagating to png on download

I am generating an svg, with text, using D3.js for a user to download.我正在使用 D3.js 生成带有文本的 svg 供用户下载。

Unfortunately, when an svg is downloaded, the font family applied to the text on the svg does not appear to be included when the svg is converted to canvas, then downloaded as a png. Unfortunately, when an svg is downloaded, the font family applied to the text on the svg does not appear to be included when the svg is converted to canvas, then downloaded as a png.

The font styling appears to be missing.字体样式似乎丢失了。

Is there a way to construct the png with this font family applied?有没有办法应用这个字体系列来构建 png?

To download the svg as a png, I adapted the answer described here .要将 svg 下载为 png,我修改了此处描述的答案。

Here is my process:这是我的过程:

First, I create the svg.首先,我创建 svg。

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

Then, I add my text elements to the svg然后,我将我的文本元素添加到 svg

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

Merriweather is a Google font family that I load in the head of a html page like so: 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>

On download, I execute the following functions on the svg,下载时,我在 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);
  }

When serialized to string the svg appears as such:当序列化为字符串时,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>

From what I can tell, the font family is being correctly specified in the string, yet when the svg is converted to canvas and then png, it is being lost.据我所知,在字符串中正确指定了字体系列,但是当 svg 转换为 canvas 然后 png 时,它正在丢失。 Why might this happen?为什么会发生这种情况?

Please let me know if I can provide any additional information.如果我可以提供任何其他信息,请告诉我。 Any assistance is greatly appreciated!非常感谢任何帮助!

To anybody who finds this with the same problem, I was able to figure it out.对于任何发现此问题的人来说,我都能弄清楚。

Thanks to Mr. Longson's suggestion, I found the following answer by Kaiido on this question .感谢Longson先生的建议,我在这个问题上找到了Kaiido的以下答案。

Kaiido's GFontToDataURI method worked perfectly. Kaiido 的 GFontToDataURI 方法运行良好。 I incorporated it into my code like so:我将它合并到我的代码中,如下所示:

            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)) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM