10

我目前正在使用 canvg() 和 Canvas2Image 将我的 SVG 复制到画布,然后将画布转换为 PNG。我想保持图像格式而不使用 PDF。

如何保持 CSS 的完整性?图表是使用 NVD3.js 制作的。

downloadPhoto: function() {
  var chartArea = document.getElementsByTagName('svg')[0].parentNode;
  var svg = chartArea.innerHTML;
  var canvas = document.createElement('canvas');
  canvas.setAttribute('width', chartArea.offsetWidth);
  canvas.setAttribute('height', chartArea.offsetHeight);
  canvas.setAttribute('display', 'none');

  canvas.setAttribute(
    'style',
    'position: absolute; ' +
    'top: ' + (-chartArea.offsetHeight * 2) + 'px;' +
    'left: ' + (-chartArea.offsetWidth * 2) + 'px;');
  document.body.appendChild(canvas);
  canvg(canvas, svg);
  Canvas2Image.saveAsPNG(canvas);
  canvas.parentNode.removeChild(canvas);
}

原始 SVG

SVG 转换为 PNG

4

3 回答 3

5

样式表中定义的 svg 元素的样式定义不会应用于生成的画布。这可以通过在调用 canvg 之前向 svg 元素添加样式定义来修补。

这篇文章的启发,我创建了这个:

function generateStyleDefs(svgDomElement) {
  var styleDefs = "";
  var sheets = document.styleSheets;
  for (var i = 0; i < sheets.length; i++) {
    var rules = sheets[i].cssRules;
    for (var j = 0; j < rules.length; j++) {
      var rule = rules[j];
      if (rule.style) {
        var selectorText = rule.selectorText;
        var elems = svgDomElement.querySelectorAll(selectorText);

        if (elems.length) {
          styleDefs += selectorText + " { " + rule.style.cssText + " }\n";
        }
      }
    }
  }

  var s = document.createElement('style');
  s.setAttribute('type', 'text/css');
  s.innerHTML = "<![CDATA[\n" + styleDefs + "\n]]>";
  //somehow cdata section doesn't always work; you could use this instead:
  //s.innerHTML = styleDefs;

  var defs = document.createElement('defs');
  defs.appendChild(s);
  svgDomElement.insertBefore(defs, svgDomElement.firstChild);
}

// generate style definitions on the svg element(s)
generateStyleDefs(document.getElementById('svgElementId'));
于 2015-08-11T18:36:25.597 回答
3

这里的关键是所有样式规则都必须是 SVG 的一部分,而不是外部样式文件。因此,您需要检查 NVD3 的所有 CSS 并在代码中设置所有这些属性。通过外部样式表设置的任何内容都将被忽略。

于 2013-12-05T09:09:09.667 回答
2

只是为了让@Lars Kotthoff 的回答更加具体。“如何直接从 svg 导出 png的示例”有一个工作示例。代码片段/要点首先尝试将所有 css 应用于 svg 内联,然后在画布上绘制图像并将数据导出为 png。(内部采用svg-crowbar代码)。我在我的项目中应用了这项技术,它运行顺利 - 一个下载按钮,可以下载使用nvd3渲染的 svg 图像。

于 2016-12-31T05:16:55.547 回答