【问题标题】:Save D3 svg as a high quality image - viewport case将 D3 svg 保存为高质量图像 - 视口案例
【发布时间】:2015-05-20 18:27:04
【问题描述】:

我正在尝试将 d3 svg 保存为基于 this 主题的高质量 png 图像。

问题是我的 svg 是响应式的,所以它没有宽度和高度属性。结果,最终的 png 看起来不正确(宽度/高度比不正确)。

我最终尝试制作一个新的 svg 元素,具有正确的宽度和高度属性并继续这个,但似乎我做错了什么。

这是我的代码:

var   w = 193,
      h = 260;
var ratio = 2;
var canvas1 = document.createElement('canvas');
canvas1.id = "canvas1";
canvas1.width = w * 2.0;
canvas1.height = h * 2.0;
document.getElementById('pngcon').appendChild(canvas1);

var svg = document.getElementById(`chartId`).querySelector('svg');

var step = document.createElement('svg');
    step.id = 'newsvg';
    step.setAttribute('width', w);
    step.setAttribute('height', h);
    step.innerHTML = $('#SupportingBeamCrossSectionSVG').html();

document.getElementById('cont').appendChild(step);

var html = new XMLSerializer().serializeToString(document.getElementById(`cont`).querySelector('svg'));

var imgsrc = 'data:image/svg+xml;base64,' + btoa(html);

var canvas = document.getElementById("canvas1");
var context = canvas.getContext("2d");
var canvasdata;
var image = new Image;
image.src = imgsrc;
image.onload = function() {
  context.drawImage(image, 0, 0, canvas.width, canvas.height);

  canvasdata = canvas.toDataURL("image/png");

  var a = document.createElement("a");
  a.id = "imagepng"
  a.innerHTML = "output file, right click - save as since click() won't work in snippet";
  a.download = "output.png";
  a.href = canvasdata;
  document.body.insertBefore(a, document.getElementById(`chartId`));
}

我创建了一个 jsfiddle here

【问题讨论】:

    标签: javascript svg d3.js


    【解决方案1】:

    要创建 SVG 元素,请执行此操作。

    var step = document.createElementNS("http://www.w3.org/2000/svg","svg");
    

    var   w = 193,
          h = 260;
    var ratio = 2
    console.log(ratio);
    var canvas1 = document.createElement('canvas');
    canvas1.id = "canvas1";
    canvas1.width = w * ratio;
    canvas1.height = h * ratio;
    document.getElementById('pngcon').appendChild(canvas1);
    
    var svg = document.getElementById(`chartId`).querySelector('svg');
    
    var step = document.createElementNS("http://www.w3.org/2000/svg","svg");
        step.id = 'newsvg';
        step.setAttribute('width', w);
        step.setAttribute('height', h);
        step.innerHTML = $('#SupportingBeamCrossSectionSVG').html();
    
    document.getElementById('cont').appendChild(step);
    
    var html = new XMLSerializer().serializeToString(document.getElementById('cont').querySelector('svg'));
    
    var imgsrc = 'data:image/svg+xml;base64,' + btoa(html);
    
    var canvas = document.getElementById("canvas1");
    var context = canvas.getContext("2d");
    var canvasdata;
    var image = new Image;
    image.src = imgsrc;
    console.log(imgsrc);
    
    image.onload = function() {
      context.drawImage(image, 0, 0, canvas.width, canvas.height);
      canvasdata = canvas.toDataURL("image/png");
      var a = document.createElement("a");
      a.id = "imagepng"
      a.innerHTML = "output file, right click - save as since click() won't work in snippet";
      a.download = "output.png";
      a.href = canvasdata;
      document.body.insertBefore(a, document.getElementById(`chartId`));
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
    <div id="chartId">
    <svg id="SupportingBeamCrossSectionSVG" version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" xml:space="preserve" viewBox="0 0 193 260" enable-background=" new 0 0 193 260" height="260" width="193" style="max-width: 193px"><path id="SupportingBeamCrossSectionSVG" d="M-36.5,-70 L36.5,-70 L36.5,-63.1 L9.35,-63.1 A7,7 1 0,02.35,-56.1 L2.35,56.1 A7,7 1 0,09.35,63.1 L36.5,63.1 L36.5,70 L-36.5,70 L-36.5,63.1 L-9.35,63.1 A7,7 1 0,0-2.35,56.1 L-2.35,-56.1 A7,7 1 0,0-9.35,-63.1 L-36.5,-63.1 Z" fill="#428bca" transform="translate(96.5, 130)"></path><g fill="#484D61" transform="translate(96.5, 130)"><circle cx="0" cy="0" r="2"></circle><line x1="0" y1="0" x2="96.5" y2="0" stroke="#484D61" stroke-width="1" stroke-dasharray="5,5"></line><line x1="0" y1="0" x2="0" y2="130" stroke="#484D61" stroke-width="1" stroke-dasharray="5,5"></line><polygon points="96.5,0 86.5,4 86.5,-4"></polygon><polygon points="0,130 -4,120 4,120"></polygon><text x="96.5" y="13.5" font-family="Verdana" font-size="10" text-anchor="end">y</text><text x="7.5" y="130" font-family="Verdana" font-size="10" text-anchor="start">z</text></g><g id="hSupportingBeam" fill="#484D61" transform="translate(15, 60)"><g transform="translate(0, 70)"><line x1="0" y1="-75" x2="0" y2="75" stroke="#484D61" stroke-width="1"></line><line x1="-5" y1="-70" x2="5" y2="-70" stroke="#484D61" stroke-width="1"></line><line x1="-5" y1="70" x2="5" y2="70" stroke="#484D61" stroke-width="1"></line><circle cx="0" cy="-70" r="2" fill="#484D61"></circle><circle cx="0" cy="70" r="2" fill="#484D61"></circle><text x="-7.5" y="0" font-size="10" font-family="Verdana" text-anchor="middle" transform="rotate(270, -7.5,0)"><tspan>140.00<tspan dy="3" font-size="10"></tspan></tspan></text></g></g><g id="tfSupportingBeam" fill="#484D61" transform="translate(40, 193.1)"><g transform="translate(0, 3.45)"><line x1="0" y1="-8.45" x2="0" y2="8.45" stroke="#484D61" stroke-width="1"></line><line x1="-5" y1="-3.45" x2="5" y2="-3.45" stroke="#484D61" stroke-width="1"></line><line x1="-5" y1="3.45" x2="5" y2="3.45" stroke="#484D61" stroke-width="1"></line><circle cx="0" cy="-3.45" r="2" fill="#484D61"></circle><circle cx="0" cy="3.45" r="2" fill="#484D61"></circle><text x="-7.5" y="0" font-size="10" font-family="Verdana" text-anchor="middle" transform="rotate(270, -7.5,0)"><tspan>6.90<tspan dy="3" font-size="10"></tspan></tspan></text></g></g><g id="heSupportingBeam" fill="#484D61" transform="translate(40, 73.9)"><g transform="translate(0, 56.1)"><line x1="0" y1="-61.1" x2="0" y2="61.1" stroke="#484D61" stroke-width="1"></line><line x1="-5" y1="-56.1" x2="5" y2="-56.1" stroke="#484D61" stroke-width="1"></line><line x1="-5" y1="56.1" x2="5" y2="56.1" stroke="#484D61" stroke-width="1"></line><circle cx="0" cy="-56.1" r="2" fill="#484D61"></circle><circle cx="0" cy="56.1" r="2" fill="#484D61"></circle><text x="-7.5" y="0" font-size="10" font-family="Verdana" text-anchor="middle" transform="rotate(270, -7.5,0)"><tspan>112.20<tspan dy="3" font-size="10"></tspan></tspan></text></g></g><g id="bSupportingBeam" fill="#484D61" transform="translate(60, 40)"><g transform="translate(36.5, 0)"><line x1="-41.5" y1="0" x2="41.5" y2="0" stroke="#484D61" stroke-width="1"></line><line x1="-36.5" y1="-5" x2="-36.5" y2="5" stroke="#484D61" stroke-width="1"></line><line x1="36.5" y1="-5" x2="36.5" y2="5" stroke="#484D61" stroke-width="1"></line><circle cx="-36.5" cy="0" r="2" fill="#484D61"></circle><circle cx="36.5" cy="0" r="2" fill="#484D61"></circle><text x="0" y="-7.5" font-size="10" font-family="Verdana" text-anchor="middle"><tspan>73.00<tspan dy="3" font-size="10"></tspan></tspan></text></g></g><g id="twSupportingBeam" fill="#484D61" transform="translate(94.15, 172)"><g transform="translate(2.35, 0)"><line x1="-7.35" y1="0" x2="7.35" y2="0" stroke="#484D61" stroke-width="1"></line><line x1="-2.35" y1="-5" x2="-2.35" y2="5" stroke="#484D61" stroke-width="1"></line><line x1="2.35" y1="-5" x2="2.35" y2="5" stroke="#484D61" stroke-width="1"></line><circle cx="-2.35" cy="0" r="2" fill="#484D61"></circle><circle cx="2.35" cy="0" r="2" fill="#484D61"></circle><text x="4.7" y="-7.5" font-size="10" font-family="Verdana" text-anchor="start"><tspan>4.70<tspan dy="3" font-size="10"></tspan></tspan></text></g></g><g transform="translate(105.85, 73.9)"><circle cx="-4.949747468305833" cy="-4.949747468305833" r="2" fill="#484D61"></circle><polyline fill="none" stroke="#484D61" points="-9.949747468305834,-9.949747468305834 4.949747468305833,9.949747468305834 39.94974746830583,9.949747468305834"></polyline><text x="22.449747468305834" y="3.4497474683058327" fill="#484D61" font-size="10" font-family="Verdana" text-anchor="middle">7.00</text></g></svg>
    </div>
    <div id="cont"></div>
    <div id="pngcon"></div>

    【讨论】:

    • chartId 中是初始的 SVG 图像,带有 viewbox 属性。 cont 是具有宽度和高度属性的新 SVG 图像。如果您选择 chartId,您将看到最终的 png 被扭曲,这就是我尝试创建新 SVG 元素的原因。
    • 我已经编辑了我的答案,我认为你这样做是一种解决方法。这就是我停止创建新 svg 元素的原因。无论如何,问题正是如此。实际上,如果我考虑一下,就没有必要创建一个新的 svg 元素。您只需设置现有 svg 元素的宽度和高度属性。
    • 如果我设置现有 svg 元素的宽度和高度,它会“失去”它的响应能力,如果我设置宽度和高度,将 svg 转换为 png,然后取消设置这些属性,它就不再存在了可见的! createElementNS 工作正常!我真的非常感谢您的宝贵时间!
    • 欢迎您。你对你所说的保持 svg 元素的响应是正确的。所以你的方法是绝对正确的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-16
    • 2018-11-24
    • 1970-01-01
    • 1970-01-01
    • 2013-02-16
    • 2012-07-26
    • 2023-02-17
    相关资源
    最近更新 更多