将2 <svg>合并为一个.SVG文件

时间:2017-08-08 14:54:12

标签: javascript html svg

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

问题是代码只导出<svg>

之一

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

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

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

这是我正在使用的代码:

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

我正在使用SVG转换(https://github.com/madebyshape/svg-convert)在页面加载之前将.SVG转换为<svg>。那部分有效,没有问题。

在这里,您可以看到代码运行:http://brand.express/projects/teste/index4.php

<svg>嵌套在另一个<svg>内是行不通的,因为它们没有嵌套。我不知道它是否因为svgConvert,但它们简单的打印在'father'<svg>之外。

2 个答案:

答案 0 :(得分:0)

目前可供下载的文件有两个问题:

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

第一个问题必须在你的JS中解决,而第二个问题可以通过指定库调用的svgCleanupAttr选项来解决:

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

你可以尝试here。我删除了此处不需要的parseStyle函数,必要时将其添加回来。

请注意,生成的svg并不完美,因为某些原因root标签没有命名空间。我的Chrome仍然可以正确显示它。

答案 1 :(得分:0)

刚刚找到了解决方案:D你必须为每个svg分组<g>..</g>并使用<g transform="translate(x,y)">代表下一组

注意:你的第二个svg似乎在Inkscape

中被破坏了

jQuery(document).ready(function($) {
  $('.svg-convert').svgConvert({
    onComplete: function() {
      // changed to css/jQuery selector
      exportSVG("#mySVG");
    }
  });
});

var exportSVG = function(svgWrapper) {
  // get the data
  var svgData = "";
  var vWidth = 0;
  var vHeight = 0;
  $(svgWrapper + " svg").each(function(i, v) {
    var viewBox = v.getAttribute('viewBox')
    if(svgData === "") {
      vWidth = parseInt(viewBox.match(/\d+ \d+ (\d+) \d+/)[1]);
      vHeight = parseInt(viewBox.match(/\d+ \d+ \d+ (\d+)/)[1]);

      svgData += '<g>' + v.innerHTML + '</g>';
    }
    else {
      var transform = parseInt(viewBox.match(/\d+ \d+ \d+ (\d+)/)[1]);
      vHeight = vHeight + transform;
      svgData += '<g transform="translate(0,' + transform + ')">' + v.innerHTML + '</g>';
    }
  })
  svgData = '<svg xmlns="http://www.w3.org/2000/svg" width="' + vWidth + '" height="' + vHeight + '" viewBox="0 0 ' + vWidth + ' ' + vHeight + '">' + svgData + '</svg>';
  //console.log(svgData)
  // 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);
};
#mySVG>svg {
  width: 40%;
  float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://brand.express/projects/teste/svg-converter.js"></script>

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