本文介绍了合并2< svg>成一个.SVG文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个页面,我有一个按钮可将所有< svg> 导出到一个.svg文件中。



问题在于代码只输出< svg> 之一。



我可以在inkscape上打开它,但只能得到其中一个svg。



我无法在浏览器上打开它,我收到一条错误消息。



我无法在illustrator上打开,我收到一条错误消息,指出该文件已损坏或类似。



这里是我使用的代码:

<!DOCTYPE html>< html xmlns =http:// www .w3.org / 1999 / xhtml>< head>< meta charset =UTF-8>< script src =https://ajax.googleapis.com/ajax/libs/jquery/2.1 .1 / jquery.min.js>< / script>< script src =svg-converter.js>< / script>< scri pt> jQuery(document).ready(function($){$('。svg-convert')。svgConvert({onComplete:function(){exportSVG(document.getElementById('mySVG')); }});});< / script>< style> #mySVG> svg {width:40%; float:left;}< / style>< / head>< body> < main id =content> < div id =mySVGxmlns =http://www.w3.org/3000/svgxmlns:xlink =http://www.w3.org/1999/xlink> < img src ='https://cdn.kastatic.org/images/avatars/svg/leafers-sapling.svg'class ='svg-convert'> < img src ='https://cdn.kastatic.org/images/avatars/svg/aqualine-sapling.svg'class ='svg-convert'> < / DIV> < / main><! - #main - > <脚本> var exportSVG = function(svg){//首先创建我们的svg节点的一个克隆,这样我们就不会混淆原始的一个var clone = svg.cloneNode(true); //解析样式parseStyles(clone); //获取数据var svgData = document.getElementById('mySVG')。innerHTML; //这里我将简单地通过下载属性var a = document.createElement('a'); a.href ='data:image / svg + xml; charset = utf8,'+ encodeURIComponent(svgData.replace(/>< / g,'> \\\
\r<')); a.download ='finalSVG.svg'; a.innerHTML ='下载.SVG文件'; document.body.appendChild(一); }; var parseStyles = function(svg){var styleSheets = []; var i; //获取文档样式表(如果svg位于< iframe>或< object>时,ownerDocument)var docStyles = svg.ownerDocument.styleSheets; //将实时StyleSheetList转换为数组以避免无限循环(i = 0; i< docStyles.length; i ++){styleSheets.push(docStyles [i]); } if(!styleSheets.length){return; } var defs = svg.querySelector('defs')|| document.createElementNS('http://www.w3.org/2000/svg','defs'); if(!defs.parentNode){svg.insertBefore(defs,svg.firstElementChild); } svg.matches = svg.matches || svg.webkitMatchesSelector || svg.mozMatchesSelector || svg.msMatchesSelector || svg.oMatchesSelector; //遍历所有文档的样式表for(i = 0; i< styleSheets.length; i ++){var currentStyle = styleSheets [i] var rules;尝试{rules = currentStyle.cssRules; } catch(e){continue; } //创建一个新的样式元素var style = document.createElement('style'); //一些样式表不能被访问并且会引发安全错误var l = rules&& rules.length; //遍历这个样式表的每个cssRules for(var j = 0; j< l; j ++){//得到这个cssRules的选择器var selector = rules [j] .selectorText; //可能是我们无法访问的外部样式表if(!selector){continue; } //是我们的svg节点还是它的一个子节点?如果((svg.matches& svg.matches(selector))|| svg.querySelector(selector)){var cssText = rules [j] .cssText; //将它追加到我们的< style>节点style.innerHTML + = cssText +'\\\
';如果我们有一些规则if(style.innerHTML){//将样式节点追加到克隆的defs defs.appendChild(style); }}}; < / script>< / html>

p>我正在使用SVG转换()在页面加载之前从.SVG转换为< svg> 。这部分工作,没有问题。



在这里你可以看到代码运行:



嵌套< svg> 在另一个< svg> 内不起作用,因为它们没有嵌套。我不知道它是否因为svgConvert,但它们简单地打印在'父'之外< svg>




  • 它包含两个< svg> 标签并排,这是无效的SVG(也不是XML)
  • < svg> 标签没有名称空间,而它们应该有一个 http://www.w3.org/2000/svg 命名空间遵守标准



第一个问题必须在JS中计算出来,而第二个问题可以通过指定<$ c您的库调用的$ c> svgCleanupAttr 选项:

  jQuery(document).ready(function $($。$ s $ $ $ $''svg-convert')。svgConvert({
onComplete:function(){
exportSVG(document.getElementById('mySVG'));
},
svgCleanupAttr:[]
});
});

var exportSVG = function(divContainer){
//首先创建一个我们svg节点的克隆,这样我们就不会混淆原始的
var svgContainer = document.createElementNS( http://www.w3.org/2000/svg,svg);
$(divContainer).find(svg)。clone()。appendTo(svgContainer);
//解析样式
// parseStyles(svgContainer);我现在不打扰它
//获取数据
var svgData = svgContainer.outerHTML;
//在这里,我将简单地通过下载属性
var a = document.createElement('a');
a.href ='data:image / svg + xml; charset = utf8,'+ encodeURIComponent(svgData);
a.download ='finalSVG.svg';
a.innerHTML ='下载.SVG文件';
document.body.appendChild(a);
};

您可以尝试。我已经移除了这里不需要的 parseStyle 函数,如果需要的话将其添加回去。



请注意,由此导致的svg并不完美,因为根标签没有命名空间。它仍然可以正确显示在我的Chrome上。


I have a page where I have a button to export all the <svg> into one single .svg file.

The problem is that the code is only exporting one of the <svg>.

I can open it on inkscape, but only get one of the svg inside.

I can't open it on my browser, I get an error message.

I can't open on illustrator, I get an error message that the file is corrupted or something like that.

Here is the code I'm using:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="svg-converter.js"></script>
<script>
jQuery(document).ready(function($) {
	$('.svg-convert').svgConvert({
    onComplete: function() {
      exportSVG(document.getElementById('mySVG'));
    }
  });
});
</script>
<style>
#mySVG > svg{
  width: 40%;
	float: left;
}
</style>
</head>
<body>
	<main id="content">
		<div id="mySVG" xmlns="http://www.w3.org/3000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
				<img src='https://cdn.kastatic.org/images/avatars/svg/leafers-sapling.svg' class='svg-convert'>
  			<img src='https://cdn.kastatic.org/images/avatars/svg/aqualine-sapling.svg' class='svg-convert'>
		</div>
	</main><!-- #main -->
	<script>
  	var exportSVG = function(svg) {
      // first create a clone of our svg node so we don't mess the original one
      var clone = svg.cloneNode(true);
      // parse the styles
      parseStyles(clone);
      // get the data
      var svgData = document.getElementById('mySVG').innerHTML;
      // here I'll just make a simple a with download attribute
      var a = document.createElement('a');
      a.href = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgData.replace(/></g, '>\n\r<'));
      a.download = 'finalSVG.svg';
      a.innerHTML = 'download the .SVG file';
      document.body.appendChild(a);
    };
    var parseStyles = function(svg) {
      var styleSheets = [];
      var i;
      // get the stylesheets of the document (ownerDocument in case svg is in <iframe> or <object>)
      var docStyles = svg.ownerDocument.styleSheets;
      // transform the live StyleSheetList to an array to avoid endless loop
      for (i = 0; i < docStyles.length; i++) {
        styleSheets.push(docStyles[i]);
      }
      if (!styleSheets.length) {
        return;
      }
      var defs = svg.querySelector('defs') || document.createElementNS('http://www.w3.org/2000/svg', 'defs');
      if (!defs.parentNode) {
        svg.insertBefore(defs, svg.firstElementChild);
      }
      svg.matches = svg.matches || svg.webkitMatchesSelector || svg.mozMatchesSelector || svg.msMatchesSelector || svg.oMatchesSelector;
      // iterate through all document's stylesheets
      for (i = 0; i < styleSheets.length; i++) {
        var currentStyle = styleSheets[i]
        var rules;
        try {
          rules = currentStyle.cssRules;
        } catch (e) {
          continue;
        }
        // create a new style element
        var style = document.createElement('style');
        // some stylesheets can't be accessed and will throw a security error
        var l = rules && rules.length;
        // iterate through each cssRules of this stylesheet
        for (var j = 0; j < l; j++) {
          // get the selector of this cssRules
          var selector = rules[j].selectorText;
          // probably an external stylesheet we can't access
          if (!selector) {
            continue;
          }
          // is it our svg node or one of its children ?
          if ((svg.matches && svg.matches(selector)) || svg.querySelector(selector)) {
            var cssText = rules[j].cssText;
           // append it to our <style> node
           style.innerHTML += cssText + '\n';
          }
        }
        // if we got some rules
        if (style.innerHTML) {
          // append the style node to the clone's defs
          defs.appendChild(style);
        }
      }
    };
  	</script>
</body>
</html>

I'm using SVG Convert (https://github.com/madebyshape/svg-convert) to convert from .SVG to <svg> before the page loads. That part works, no problem there.

Here you can see the code runing: http://brand.express/projects/teste/index4.php

Nesting the <svg> inside another <svg> doesn't work because they don't get nested. I don't know if its because of the svgConvert, but they simple are printed outside the 'father' <svg>.

解决方案

Currently the file available for download has two problems :

  • it contains two <svg> tags side-by-side, which isn't valid SVG (nor XML)
  • the <svg> tags have no namespace, while they should have a http://www.w3.org/2000/svg namespace to respect the standards

The first problem must be worked out in your JS, while the second can be fixed by specifying the svgCleanupAttr option of your library call:

jQuery(document).ready(function($) {
  $('.svg-convert').svgConvert({
    onComplete: function() {
      exportSVG(document.getElementById('mySVG'));
    },
    svgCleanupAttr: []
  });
});

var exportSVG = function(divContainer) {
  // first create a clone of our svg node so we don't mess the original one
  var svgContainer = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  $(divContainer).find("svg").clone().appendTo(svgContainer);
  // parse the styles
  //parseStyles(svgContainer); I didn't bother with it for now
  // get the data
  var svgData = svgContainer.outerHTML;
  // here I'll just make a simple a with download attribute
  var a = document.createElement('a');
  a.href = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgData);
  a.download = 'finalSVG.svg';
  a.innerHTML = 'download the .SVG file';
  document.body.appendChild(a);
};

You can try it here. I've removed the parseStyle function which wasn't needed here, add it back if necessary.

Note that the resulting svg isn't perfect, for some reason the root tag has no namespace. It was still correctly displayed by my Chrome.

这篇关于合并2&lt; svg&gt;成一个.SVG文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 01:21
查看更多