简体   繁体   English

将 svg 转换为 png 时如何包含 CSS 样式

[英]How to Include CSS style when converting svg to png

i've created a simple SVG elment that get dowbloaded to png when clicking on a button, my solution is similiar to here我创建了一个简单的 SVG 元素,单击按钮时可以将其下载为 png,我的解决方案与此处类似


The basic idea is:基本思想是:
1.svg to canvas 1.svg 到画布
2.canvas to dataUrl 2.canvas转dataUrl
3.trigger download from dataUrl 3.trigger从dataUrl下载

the problem is that when downloading the png file it doesnt include the css style applied on the svg my solution result问题是,下载 png 文件时,它不包含应用于 svg我的解决方案结果的 css 样式

NOTICE - I know there is a workingaround solution by moving the styles "inline" on the elements like here or the recursive solution by digging the DOM tree and using getComputedStyle(element,null);注意 - 我知道有一个变通的解决方案,通过在这里这样的元素上“内联”移动样式或通过挖掘 DOM 树并使用getComputedStyle(element,null);的递归解决方案

Questions:问题:
1.what's the real reason and the solution for this issue. 1.这个问题的真正原因和解决方案是什么。
(is the GPU acceleration related in anyway?) (无论如何都与GPU加速有关?)
2.how i still overcome this issue when using a custom font with Fontface 2.我如何在 Fontface 中使用自定义字体时仍然克服这个问题

 <button id="btn">svg to png</button>

  <svg id="svg" width="200" height="200">
    <circle cx="50" cy="50" r="30" />
    <text class="svgTxt" x="0" y="100">Hen's SVG Image</text>
  </svg>
  <canvas id="canvas"  width="200" height="200"></canvas>

my CSS:我的 CSS:

  /*adding exo2 font*/
    @font-face {
    font-family: 'exo_2black';
    src: url('./exo2font/Exo2-Black-webfont.eot');
    src: url('./exo2font/Exo2-Black-webfont.eot?#iefix') format('embedded-opentype'),
         url('./exo2font/Exo2-Black-webfont.woff') format('woff'),
         url('./exo2font/Exo2-Black-webfont.ttf') format('truetype'),
         url('./exo2font/Exo2-Black-webfont.svg#exo_2black') format('svg');
    font-weight: normal;
    font-style: normal;

}
/*change circle color depends on window size*/
@media screen and (min-width: 480px) {
    svg circle {
        fill: lightgreen;
    }
}
/*style on the svg text*/
    .svgTxt{
      font-family: 'exo_2black';
      font-size: 30px;
      fill: red;
    }

my code:我的代码:

  //reference to elements
    var btn = document.querySelector('#btn');
    var svg = document.getElementById('svg');
    var svgTexts = svg.getElementsByTagName('text');
    var canvas = document.getElementById('canvas');
    //Style definitions for svg elements defined in stylesheets are not applied to the generated canvas. This can be patched by adding style definitions to the svg elements before calling canvg.
  //3.trigger download from dataUrl
    function triggerDownload(imgURI) {
      var evt = new MouseEvent('click', {
        view: window,
        bubbles: false,
        cancelable: true
      });

      var a = document.createElement('a');
      a.setAttribute('download', 'hen_saved_image.png');
      a.setAttribute('href', imgURI);
      a.setAttribute('target', '_blank');
      a.dispatchEvent(evt);
    }
    //btn click event
    btn.addEventListener('click', function () {
      // 1.svg to canvas
      var ctx = canvas.getContext('2d');
      var data = (new XMLSerializer()).serializeToString(svg);//serialize the svg element to string
      var DOMURL = window.URL || window.webkitURL || window;
      var img = new Image();
      var svgBlob = new Blob([data], { type: 'image/svg+xml;charset=utf-8' });//A blob object represents a chuck of bytes that holds data of a file.
      var url = DOMURL.createObjectURL(svgBlob);//creates a DOMString containing an URL representing the object given in paramete
      $('svg').append(deletedSVGText);
      img.onload = function () {
        ctx.drawImage(img, 0, 0);
        DOMURL.revokeObjectURL(url);
        // 2.canvas to dataUrl
        var imgURI = canvas
          .toDataURL('image/png')
          .replace('image/png', 'image/octet-stream');// returns a data URI containing a representation of the image in the format specified by the type parameter

        triggerDownload(imgURI);
      };
      img.src = url;
    });

Question 1 (first half): what's the real reason (is the GPU acceleration related in anyway?)问题 1(前半部分):真正的原因什么(无论如何与 GPU 加速有关?)

No, GPU acceleration has nothing to do with it.不,GPU 加速与此无关。
The broadest reason is privacy .最广泛的原因是隐私

To draw your svg with drawImage you have to load your svg as an external document inside an <img> tag.要使用drawImage绘制 svg,您必须将 svg 作为外部文档加载到<img>标签内。 SVG can be quite a complex image format for resources loading (it can literally require any kind of resource that could be required by any HTML document). SVG 可以是一种非常复杂的资源加载图像格式(它实际上可以需要任何 HTML 文档可能需要的任何类型的资源)。 Thus, it has been stated in specs that the same security as the one for <iframe> elements or <object> or similar ones should apply to <img> content and even stricter :因此,规范中已经声明,与<iframe>元素或<object>或类似元素相同的安全性应该适用于<img>内容,甚至更严格:

<img> content can not require any external resources, nor access to the main document. <img>内容不能需要任何外部资源,也不能访问主文件。

Question 1 (second half) : and the solution for this issue问题1(下半场)以及这个问题的解决方案

You pointed to some SO questions already answering it, you could also just include all the stylesheets from the main document inside a <style> tag inside your parsed svg Node, before you do create the Blob from it.您指出了一些已经回答的 SO 问题,您也可以在从它创建 Blob 之前,将主文档中的所有样式表包含在解析的 svg 节点内的<style>标记中。 dumb implementation here 愚蠢的实现在这里

Question 2 : "how i still overcome this issue when using a custom font with Fontface"问题 2: “我如何在 Fontface 中使用自定义字体时仍然克服这个问题”

For external resources, you have to encode it as dataURI, and include it in your svg node before you create the Blob.对于外部资源,您必须将其编码为 dataURI,并在创建 Blob 之前将其包含在您的 svg 节点中。 For font in particular, you'd set a font-face property in a <style> element.特别是对于字体,您需要在<style>元素中设置font-face属性。

So at the end, your svg would have something like所以最后,你的 svg 会有类似的东西

<defs>
  <style>
    /* all your parsed styles in here */
    @font-face {
     font-family: foo;
     src: url('data:application/font-woff;charset=utf-8;base64,...')
    }
  </style>
</defs>

in itself before you do extract its markup.在你提取它的标记之前。

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

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