2

我有从服务器动态加载的内联 svg。我希望使用内联 css 对 svg 进行操作或修改。我已经搜索了将修改后的 svg 转换为 png 或 base64 图像。经过长时间的搜索,我决定坚持使用 Canvg。

现在的问题是它渲染了内联样式属性,如背景和边框半径。

这是我的svg。

<svg height="550" width="550" viewBox="0 0 512 512" id="svg">
<path d="m309 139c0-111-32-139-53-139-21 0-53 28-53 139l-173 122c-2 1-4 4-4 7l0 46c0 6 5 10 11 9l166-37c6 49 16 93 23 139l-63 49c-2 1-4 4-4 6l0 23c0 7 6 11 12 8l85-38 85 38c6 3 12-1 12-8l0-23c0-2-2-5-4-6l-63-49c7-46 17-90 23-139l166 37c6 1 11-3 11-9l0-46c0-3-2-6-4-7z m-53-88c-11 0-21 3-30 7 3-13 15-22 30-22 15 0 27 9 30 22-9-4-19-7-30-7z"></path>
</svg>

看起来像这样:

原始 Svg Preivew

请记住,路径是从服务器动态加载的。所以不能修改。

现在我想像这样操纵它。

<svg style="background: grey none repeat scroll 0% 0%; fill: white; padding: 70px; border-radius: 98px;" height="550" width="550" viewBox="0 0 512 512" id="svg">
      <path d="m309 139c0-111-32-139-53-139-21 0-53 28-53 139l-173 122c-2 1-4 4-4 7l0 46c0 6 5 10 11 9l166-37c6 49 16 93 23 139l-63 49c-2 1-4 4-4 6l0 23c0 7 6 11 12 8l85-38 85 38c6 3 12-1 12-8l0-23c0-2-2-5-4-6l-63-49c7-46 17-90 23-139l166 37c6 1 11-3 11-9l0-46c0-3-2-6-4-7z m-53-88c-11 0-21 3-30 7 3-13 15-22 30-22 15 0 27 9 30 22-9-4-19-7-30-7z"></path>      </svg>

看起来像这样:

人工处理的图像

但是在使用canvg脚本渲染之后。它呈现为原始文件。它只包括填充颜色。没有其他的。

有没有其他方法可以做到这一点。使用画布或 svg 元素。

请帮忙!!!提前致谢

4

2 回答 2

2

大多数 svg 到画布库不支持外部资源(xlink 属性、图像和 CSS)。

我发现这样做的唯一方法是将这些外部资源附加到 svg 节点中,然后使用该canvas.toDataURL()方法将您的 svg 绘制到画布上。

我正在编写一个小脚本来处理这个问题,这里是我制作的 CSS 解析器的转储,它将遍历所有文档的样式表,并且只附加那些对内部元素有影响的样式表。

var parseStyles = function() {
    var styleSheets = [],
        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) {
        // getDef() will return an svg <defs> element if already into the node, or will create it otherwise
        getDef();
        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++) {
        // create a new style element
        var style = document.createElement('style');
        // some stylesheets can't be accessed and will throw a security error
        try {
            var rules = styleSheets[i].cssRules,
                l = 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;
                // is it our svg node or one of its children ?
                if ((svg.matches && svg.matches(selector)) || svg.querySelector(selector)) {
                    // append it to our <style> node
                    style.innerHTML += rules[j].cssText + '\n';
                }
            }
            // if we got some rules
            if (style.innerHTML) {
                // append the style node to the clone's defs
                defs.appendChild(style);
            }
        } catch (e) {
            console.warn('unable to get some cssRules : ', e);
        }
    }
    // small hack to avoid border and margins being applied inside the <img>
    var s = clone.style;
    s.border = s.padding = s.margin = 0;
    s.transform = 'initial';
};

var svg = document.querySelector('svg');
var doSomethingWith = function(canvas) {
  document.body.appendChild(canvas)
};



var parseStyles = function() {
  var styleSheets = [],
    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) {
    // getDef() will return an svg <defs> element if already into the node, or will create it otherwise
    getDef();
    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++) {
    // create a new style element
    var style = document.createElement('style');
    // some stylesheets can't be accessed and will throw a security error
    try {
      var rules = styleSheets[i].cssRules,
        l = 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;
        // is it our svg node or one of its children ?
        if ((svg.matches && svg.matches(selector)) || svg.querySelector(selector)) {
          // append it to our <style> node
          style.innerHTML += rules[j].cssText + '\n';
        }
      }
      // if we got some rules
      if (style.innerHTML) {
        // append the style node to the clone's defs
        defs.appendChild(style);
      }
    } catch (e) {
      console.warn('unable to get some cssRules : ', e);
    }
  }
  // small hack to avoid border and margins being applied inside the <img>
  var s = svg.style;
  s.border = s.padding = s.margin = 0;
  s.transform = 'initial';
  exportDoc();
};

var defs;
var getDef = function() {
  // Do we have a `<defs>` element already ?
  defs = svg.querySelector('defs') || document.createElementNS('http://www.w3.org/2000/svg', 'defs');
  if (!defs.parentNode) {
    svg.insertBefore(defs, svg.firstElementChild);
  }
};

var exportDoc = function() {
  // check if our svgNode has width and height properties set to absolute values
  // otherwise, canvas won't be able to draw it
  var bbox = svg.getBoundingClientRect();

  if (svg.width.baseVal.unitType !== 1) svg.setAttribute('width', bbox.width);
  if (svg.height.baseVal.unitType !== 1) svg.setAttribute('height', bbox.height);

  // serialize our node
  var svgData = (new XMLSerializer()).serializeToString(svg);
  // remember to encode special chars
  var svgURL = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgData);

  var svgImg = new Image();

  svgImg.onload = function() {
    var canvas = document.createElement('canvas');
    // IE11 doesn't set a width on svg images...
    canvas.width = this.width || bbox.width;
    canvas.height = this.height || bbox.height;

    canvas.getContext('2d').drawImage(svgImg, 0, 0, canvas.width, canvas.height);
    doSomethingWith(canvas)
  };

  svgImg.src = svgURL;
};

parseStyles();
rect {
  fill: red;
  padding: 25em;
  border: 25px solid yellow;
}
canvas {
  border: 1px solid green;
}
svg{
  background-color: skyblue;
}
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" version="1.1">
  <rect x="0" y="0" width="100" height="100" />
</svg>

于 2015-12-07T01:56:00.647 回答
1

您可以使用 Javascript 和 DOM 来修改当前页面中的任何元素;无论它是服务器生成文件还是其他任何东西。 http://www.i-programmer.info/programming/graphics-and-imaging/3254-svg-javascript-and-the-dom.html

于 2015-12-06T18:44:31.263 回答