【问题标题】:How to Include CSS style when converting svg to png将svg转换为png时如何包含CSS样式
【发布时间】:2017-05-25 02:34:40
【问题描述】:

我创建了一个简单的 SVG 元素,在单击按钮时会下载到 png,我的解决方案类似于 here


基本思路是:
1.svg 到画布
2.canvas转dataUrl
3.触发从dataUrl下载

问题是在下载 png 文件时,它不包含应用于 svg 的 css 样式 my solution result

注意 - 我知道有一个解决方法是通过移动元素上的“内联”样式,如 here 或通过挖掘 DOM 树并使用递归解决方案 getComputedStyle(element ,null);

问题:
1.这个问题的真正原因和解决方案是什么。
(GPU加速是否与此有关?)
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>

我的 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;
    }

我的代码:

  //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;
    });

【问题讨论】:

    标签: css canvas svg html5-canvas png


    【解决方案1】:

    问题 1(上半部分): 真正的原因是什么(GPU 加速是否与此有关?)

    不,GPU 加速与此无关。
    最广泛的原因是隐私。

    要使用drawImage 绘制您的svg,您必须将您的svg 作为外部文档加载到&lt;img&gt; 标记内。 SVG 可以是一种用于资源加载的非常复杂的图像格式(它实际上可以需要任何 HTML 文档可能需要的任何类型的资源)。因此,规范中已声明与&lt;iframe&gt; 元素或&lt;object&gt; 或类似元素的安全性相同,应适用于&lt;img&gt; 内容,甚至更严格:

    &lt;img&gt; 内容不能需要任何外部资源,也不能访问主文档。

    问题 1(下半场):以及这个问题的解决方案

    您指出了一些已经回答它的 SO 问题,您也可以将主文档中的所有样式表包含在解析的 svg 节点中的 &lt;style&gt; 标记中,然后再从它创建 Blob。 dumb implementation here

    问题 2: “在使用带有 Fontface 的自定义字体时,我如何克服这个问题”

    对于外部资源,您必须将其编码为 dataURI,并在创建 Blob 之前将其包含在您的 svg 节点中。特别是对于字体,您需要在 &lt;style&gt; 元素中设置 font-face 属性。

    所以最后,你的 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>
    

    在您提取其标记之前就在其本身。

    【讨论】:

      猜你喜欢
      • 2016-01-16
      • 2018-05-10
      • 2011-12-31
      • 2021-04-24
      • 2014-09-16
      • 2016-04-27
      相关资源
      最近更新 更多