如何在将svg转换为png时包含CSS样式 [英] How to Include CSS style when converting svg to png

查看:477
本文介绍了如何在将svg转换为png时包含CSS样式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个简单的SVG元素,当点击一个按钮时,它会被下载到png,我的解决方案类似于这里





基本想法是:

1。 svg到画布

2.canvas到dataUrl

3.trigger从dataUrl下载



问题是当下载png文件时,它不包括应用于svg上的css样式
我的解决方案结果



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



问题:
< br>
1.这是此问题的真正原因和解决方案。
(是否与GPU加速相关?)

2 。我仍然克服这个问题时使用自定义字体与Fontface

 < button id =btn > svg到png< / button> 

< svg id =svgwidth =200height =200>
< circle cx =50cy =50r =30/>
< text class =svgTxtx =0y =100> Hen的SVG图像< / text>
< / svg>
< canvas id =canvaswidth =200height =200>< / canvas>

我的CSS:

  / *添加exo2字体* / 
@ 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;

}
/ *更改圈子颜色取决于窗口大小* /
@media屏幕和(min-width:480px){
svg circle {
fill:lightgreen;
}
}
/ * svg文本上的样式* /
.svgTxt {
font-family:'exo_2black';
font-size:30px;
fill:red;
}

我的代码:

  //对元素的引用
var btn = document.querySelector('#btn');
var svg = document.getElementById('svg');
var svgTexts = svg.getElementsByTagName('text');
var canvas = document.getElementById('canvas');
//样式表中定义的svg元素的样式定义不应用于生成的画布。这可以通过在调用canvg之前向svg元素添加样式定义来修补。
//3.trigger从dataUrl下载
function triggerDownload(imgURI){
var evt = new MouseEvent('click',{
view:window,
bubble :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事件
btn.addEventListener('click',function(){
// 1.svg到canvas
var ctx = canvas。 getContext('2d');
var data =(new XMLSerializer())serializeToString(svg); //将svg元素序列化为字符串
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); //创建一个DOMString,它包含一个表示在参数中给出的对象的URL
$(' 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') ; //以类型参数指定的格式返回包含图像表示形式的数据URI

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


解决方案

问题1 / strong>



没有,GPU加速是什么?与它无关。

最宽泛的原因是隐私



要使用 drawImage 绘制svg,必须将svg作为外部文档加载到< img> 标记。 SVG可以是相当复杂的图像格式的资源加载(它可以字面上需要任何类型的资源,任何HTML文档可能需要)。因此,在规范中已经说明了与< iframe> 元素或< object> 或类似内容应适用于< img> 内容,甚至更严格:



< img> 内容不能要求任何外部资源,也不能访问主文档。



问题1 )和此问题的解决方案



您指出了一些已经回答的问题,从主文档中的样式表在解析的svg Node内的< style> 标记中,然后从中创建Blob。 这里的愚蠢实现



问题2: 在使用Fontface自定义字体时如何解决这个问题



外部资源,您必须将其编码为dataURI,并在创建Blob之前将其包括在您的svg节点中。对于字体,您可以在< style> 元素中设置 font-face p>

所以最后,你的svg会有像

  defs> 
< style>
/ *所有你解析的样式在这里* /
@ font-face {
font-family:foo;
src:url('data:application / font-woff; charset = utf-8; base64,...')
}
< / style>
< / defs>

在您解压缩标记之前。


i've created a simple SVG elment that get dowbloaded to png when clicking on a button, my solution is similiar to here


The basic idea is:
1.svg to canvas
2.canvas to dataUrl
3.trigger download from dataUrl

the problem is that when downloading the png file it doesnt include the css style applied on the svg my solution result

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

Questions:
1.what's the real reason and the solution for this issue.
(is the GPU acceleration related in anyway?)
2.how i still overcome this issue when using a custom font with 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:

  /*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?)

No, GPU acceleration has nothing to do with it.
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. 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). 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 :

<img> content can not require any external resources, nor access to the main document.

Question 1 (second half): and the solution for this issue

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. dumb implementation here

Question 2 : "how i still overcome this issue when using a custom font with Fontface"

For external resources, you have to encode it as dataURI, and include it in your svg node before you create the Blob. For font in particular, you'd set a font-face property in a <style> element.

So at the end, your svg would have something like

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

这篇关于如何在将svg转换为png时包含CSS样式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆