简体   繁体   English

SVG到图像转换的麻烦

[英]SVG to image conversion trouble

I'm trying to convert the following SVG string to image with JS: 我正在尝试使用JS将以下SVG字符串转换为图像:

<svg xmlns:ct="http://gionkunz.github.com/chartist-js/ct" width="100%" height="100%" class="ct-chart-line" id="test-chart" style="width: 100%; height: 100%;"><g class="ct-grids"><line y1="165" y2="165" x1="50" x2="406.984375" class="ct-grid ct-vertical"></line><line y1="115" y2="115" x1="50" x2="406.984375" class="ct-grid ct-vertical"></line><line y1="65" y2="65" x1="50" x2="406.984375" class="ct-grid ct-vertical"></line><line y1="15" y2="15" x1="50" x2="406.984375" class="ct-grid ct-vertical"></line></g><g><g series-name="performance" class="ct-series ct-series-a"><path d="M50,165C53.57,165,403.415,155,406.984,155" class="ct-line"></path></g><g series-name="bemchmark" class="ct-series ct-series-b"><path d="M50,165C53.57,165,403.415,45,406.984,45" class="ct-line"></path></g></g><g class="ct-labels"><foreignObject style="overflow: visible;" x="40" y="170" width="356.984375" height="20"><span class="lineChartLabel ct-horizontal ct-end" style="width: 357px; height: 20px" xmlns="http://www.w3.org/2000/xmlns/">Jan</span></foreignObject><foreignObject style="overflow: visible;" x="396.984375" y="170" width="30" height="20"><span class="lineChartLabel ct-horizontal ct-end" style="width: 30px; height: 20px" xmlns="http://www.w3.org/2000/xmlns/">Feb</span></foreignObject><foreignObject style="overflow: visible;" y="115" x="10" height="50" width="30"><span class="lineChartLabel ct-vertical ct-start" style="height: 50px; width: 30px" xmlns="http://www.w3.org/2000/xmlns/">0%</span></foreignObject><foreignObject style="overflow: visible;" y="65" x="10" height="50" width="30"><span class="lineChartLabel ct-vertical ct-start" style="height: 50px; width: 30px" xmlns="http://www.w3.org/2000/xmlns/">0.5%</span></foreignObject><foreignObject style="overflow: visible;" y="15" x="10" height="50" width="30"><span class="lineChartLabel ct-vertical ct-start" style="height: 50px; width: 30px" xmlns="http://www.w3.org/2000/xmlns/">1%</span></foreignObject><foreignObject style="overflow: visible;" y="-15" x="10" height="30" width="30"><span class="lineChartLabel ct-vertical ct-start" style="height: 30px; width: 30px" xmlns="http://www.w3.org/2000/xmlns/">1.5%</span></foreignObject></g></svg>  

I tried everything I could find, like simg.js or this script, for example: 我尝试了所有可能找到的内容,例如simg.js或此脚本,例如:

var svg  = document.getElementById('test-chart'),
xml  = new XMLSerializer().serializeToString(svg),
data = "data:image/svg+xml;base64," + btoa(xml),
img  = new Image();
img.setAttribute('src', data)
document.body.appendChild(img)

But the generated image is always "broken", ie doesn't appear at all. 但是生成的图像始终“破碎”,即根本不出现。 The same script with a simpler SVG string works just fine. 具有更简单的SVG字符串的相同脚本也可以正常工作。

I don't understand exactly what's wrong with my string, which is generated by chartist.js and displays nicely in the browser, but it seems the culprit are the <foreignObject> elements, as if I remove them, things work fine. 我不完全了解我的字符串出了什么问题,该字符串是由chartist.js生成并在浏览器中很好地显示的,但是罪魁祸首是<foreignObject>元素,就像我删除它们一样,一切正常。

Is there a way to convert that SVG string into an image with JS? 有没有一种方法可以使用JS将SVG字符串转换为图像?

Your problem is that the xmlns attribute set on the <span> elements contained in the <foreignObjects> are wrong. 您的问题是在<foreignObjects>中包含的<span>元素上设置的xmlns属性是错误的。 Currently they are set to http://www.w3.org/2000/xmlns/ which is the default XML namespace. 当前,它们设置为http://www.w3.org/2000/xmlns/ ,这是默认的XML名称空间。 It should be http://www.w3.org/1999/xhtml since the element you are including belong to the xhtml namespace. 它应该是http://www.w3.org/1999/xhtml因为要包含的元素属于xhtml命名空间。

I do believe that you didn't set that yourself and that the library you do use did this. 我确实相信您没有设置自己,并且您使用的库确实做到了这一点。

You could leave its authors an issue report, but note that IE<11 didn't support this <foreignObject> tag, and that current Safari have some security restrictions on <img> tag representing such a tag (if you want to draw it back to a canvas, it will taint this one). 您可以给它的作者一个问题报告,但请注意IE <11不支持此<foreignObject>标签,并且当前的Safari在表示该标签的<img>标签上有一些安全限制(如果您想将其退回)到画布上,它会弄脏这个)。 So in my personal opinion the use of this tag is still not recommended. 因此,以我个人的观点 ,仍然不建议使用此标签。

Also note that, as others said, you have to set absolute width and height attribute to the root <svg> so it displays correctly in <img> tag. 还要注意,正如其他人所说,您必须将根的绝对widthheight属性设置为根<svg>以便它在<img>标记中正确显示。

Finally, you don't need to base64 encode your string, and the 'data:image/svg+xml; charset=utf8, ' 最后,您不需要对字符串进行base64编码,而'data:image/svg+xml; charset=utf8, ' 'data:image/svg+xml; charset=utf8, ' dataURI header is the only one supported by all browsers from IE9 to Edge. 'data:image/svg+xml; charset=utf8, ' dataURI标头是从IE9到Edge的所有浏览器唯一支持的标头。

Here is how your markup should look like : 这是您的标记应如下所示:

 var svgData = (new XMLSerializer()).serializeToString(test) var dataURI = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgData); var img = new Image(); img.src = dataURI; document.body.appendChild(img); 
 <h3> svg version </h3> <svg xmlns:ct="http://gionkunz.github.com/chartist-js/ct" width="500" height="200" class="ct-chart-line" id="test" style="width: 100%; height: 100%;"> <g class="ct-grids"> <line y1="165" y2="165" x1="50" x2="406.984375" class="ct-grid ct-vertical"></line> <line y1="115" y2="115" x1="50" x2="406.984375" class="ct-grid ct-vertical"></line> <line y1="65" y2="65" x1="50" x2="406.984375" class="ct-grid ct-vertical"></line> <line y1="15" y2="15" x1="50" x2="406.984375" class="ct-grid ct-vertical"></line> </g> <g> <g series-name="performance" class="ct-series ct-series-a"> <path d="M50,165C53.57,165,403.415,155,406.984,155" class="ct-line"></path> </g> <g series-name="bemchmark" class="ct-series ct-series-b"> <path d="M50,165C53.57,165,403.415,45,406.984,45" class="ct-line"></path> </g> </g> <g class="ct-labels"> <foreignObject style="overflow: visible;" x="40" y="170" width="356.984375" height="20" requiredExtensions="http://www.w3.org/1999/xhtml"><span class="lineChartLabel ct-horizontal ct-end" style="width: 357px; height: 20px" xmlns="http://www.w3.org/1999/xhtml">Jan</span></foreignObject> <foreignObject style="overflow: visible;" x="396.984375" y="170" width="30" height="20"><span class="lineChartLabel ct-horizontal ct-end" style="width: 30px; height: 20px" xmlns="http://www.w3.org/1999/xhtml">Feb</span></foreignObject> <foreignObject style="overflow: visible;" y="115" x="10" height="50" width="30" ><span class="lineChartLabel ct-vertical ct-start" style="height: 50px; width: 30px" xmlns="http://www.w3.org/1999/xhtml">0%</span></foreignObject> <foreignObject style="overflow: visible;" y="65" x="10" height="50" width="30" ><span class="lineChartLabel ct-vertical ct-start" style="height: 50px; width: 30px" xmlns="http://www.w3.org/1999/xhtml">0.5%</span></foreignObject> <foreignObject style="overflow: visible;" y="15" x="10" height="50" width="30" ><span class="lineChartLabel ct-vertical ct-start" style="height: 50px; width: 30px" xmlns="http://www.w3.org/1999/xhtml">1%</span></foreignObject> <foreignObject style="overflow: visible;" y="-15" x="10" height="30" width="30" ><span class="lineChartLabel ct-vertical ct-start" style="height: 30px; width: 30px" xmlns="http://www.w3.org/1999/xhtml">1.5%</span></foreignObject> </g> </svg> <h3> img version </h3> 

So if you can't fix the issue before, you'll have to loop through all your HTML elements contained into the <foreignObject> elements and fix that manually ( HTMLelem.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml') ) 因此,如果您之前无法解决问题,则必须遍历<foreignObject>元素中包含的所有HTML元素,然后手动进行修复( HTMLelem.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')

you can use fabric js: http://fabricjs.com/ 您可以使用Fabric js: http//fabricjs.com/

var addShape = function(shapeName) {

fabric.loadSVGFromURL('../assets/' + shapeName + '.svg', function(objects, options) {
  var loadedObject = fabric.util.groupSVGElements(objects, options);
   loadedObject.set({
     left: 0,
     top:0,
     angle:0
   }).setCoords();
  canvas.add(loadedObject);
  window.open(canvas.toDataURL('png'));
  });
};

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

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