将 svg 转换为 png 时如何包含 CSS 样式 [英] How to Include CSS style when converting svg to png
问题描述
我创建了一个简单的 SVG 元素,单击按钮时可以下载到 png,我的解决方案类似于
问题 2 : 在使用带有 Fontface 的自定义字体时,我如何仍然克服这个问题"
对于外部资源,您必须将其编码为 dataURI,并在创建 Blob 之前将其包含在您的 svg 节点中.特别是对于字体,您需要在 元素中设置
font-face
属性.
所以最后,你的 svg 会有类似的内容
<风格>/* 所有你解析的样式都在这里 */@字体脸{字体系列:foo;src: url('data:application/font-woff;charset=utf-8;base64,...')}</风格></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屋!