我正在尝试下载生成的SVG图,在我的本地系统上作为PNG。为此,我创建了一个模态表单,它以复选框(对于PNG / JPEG)的形式接受输入,然后准备下载。我尝试了一种方法,序列化SVG,然后下载它。但是,它会导致XMLSerializer错误。需要一些帮助。感谢。
代码:
模态表格
<div class="modal-body">
<div class="form-group row" required>
<div class="col-sm-4"><label class="checkbox-inline"><input id='input1' name="selected_level" type="checkbox" autocomplete="off" value="jpg"> PNG </label></div>
<div class="col-sm-4"><label class="checkbox-inline"><input id='input2' name="selected_level" type="checkbox" autocomplete="off" value="fits"> JPG </label></div>
<div class="col-sm-4"><label class="checkbox-inline"><input id='input3' name="selected_level" type="checkbox" autocomplete="off" value="fits"> SVG </label></div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary" id="submitValue4" onclick="download_plot()">Prepare Download</button>
</div>
</div>
</div>
</div>
我的SVG :(在绘图函数中声明)
var svg = d3.select("#panelDiv").
append("svg")
.attr("width", width)
.attr("height", height)
.attr("class", "s1")
.attr("id", "svg1");
下载功能:
function download_plot()
{
if (document.getElementById('input1').checked) {
var width = 550;
var height = 560;
var svg = document.getElementsByClassName("svg1");
var serializer = new XMLSerializer();
var source = serializer.serializeToString(svg);
if(!source.match(/^<svg[^>]+xmlns="http\:\/\/www\.w3\.org\/2000\/svg"/)){
source = source.replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg"');
}
if(!source.match(/^<svg[^>]+"http\:\/\/www\.w3\.org\/1999\/xlink"/)){
source = source.replace(/^<svg/, '<svg xmlns:xlink="http://www.w3.org/1999/xlink"');
}
source = '<?xml version="1.0" standalone="no"?>\r\n' + source;
var url = "data:image/svg+xml;charset=utf-8,"+encodeURIComponent(source);
document.getElementById("link").href = url;
}
else {
console.log("Something");
}
}
答案 0 :(得分:0)
某些绘图库(例如,绘图)具有“另存为...”图像文件的内置功能。但是,如果您已经创建了<svg>
元素,并且只想将其转换为PNG图像,则可以使用第三方nodejs包,例如save-svg-as-png
- 首先,下载库的独立脚本,并在您的html页面中包含<script src="SaveSvgAsPng.js">
(无论您在何处提供脚本)。
对我有用的是使用“onclick”按钮来调用我的saveImage()
函数 - 它使用库将顶级svg元素转换为data:image/png;...
uri,并打开显示该图像的新窗口。这允许用户直接从弹出窗口打印或保存它。
function saveImage(svgId) {
var topsvg = document.querySelector("#" + svgId);
var pngwin = window.open('', 'svgpng', "titlebar=no,location=no,resizable,menubar,tabbar,dialog");
getImageUri(topsvg, {
height: topsvg.height,
width: topsvg.width
},
function(pnguri) {
pngwin.document.head.innerHTML = "<title>PNG Image</title>";
pngwin.document.body.style = "margin: 0;";
pngwin.document.body.innerHTML = "<img src='" + pnguri + "'/>";
});
}
<button onclick="saveImage('main-svg')" style="float: left;">Save as PNG</button>
<svg id="main-svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="300" style="background: rgb(255, 255, 255);"><defs id="defs-e9bae5"><g class="clips"><clipPath id="clipe9bae5xyplot" class="plotclip"><rect width="216" height="120"></rect></clipPath><clipPath class="axesclip" id="clipe9bae5x"><rect x="80" y="0" width="216" height="300"></rect></clipPath><clipPath class="axesclip" id="clipe9bae5y"><rect x="0" y="100" width="400" height="120"></rect></clipPath><clipPath class="axesclip" id="clipe9bae5xy"><rect x="80" y="100" width="216" height="120"></rect></clipPath></g><g class="gradients"></g></defs><g class="bglayer"><rect class="bg" x="80" y="100" width="216" height="120" style="fill: rgb(255, 255, 255); fill-opacity: 1; stroke-width: 0;"></rect></g><g class="draglayer cursor-crosshair"><g class="xy"><rect class="nsewdrag drag" data-subplot="xy" x="80" y="100" width="216" height="120" style="fill: transparent; stroke-width: 0; pointer-events: all;"></rect><rect class="nwdrag drag cursor-nw-resize" data-subplot="xy" x="60" y="80" width="20" height="20" style="fill: transparent; stroke-width: 0; pointer-events: all;"></rect><rect class="nedrag drag cursor-ne-resize" data-subplot="xy" x="296" y="80" width="20" height="20" style="fill: transparent; stroke-width: 0; pointer-events: all;"></rect><rect class="swdrag drag cursor-sw-resize" data-subplot="xy" x="60" y="220" width="20" height="20" style="fill: transparent; stroke-width: 0; pointer-events: all;"></rect><rect class="sedrag drag cursor-se-resize" data-subplot="xy" x="296" y="220" width="20" height="20" style="fill: transparent; stroke-width: 0; pointer-events: all;"></rect><rect class="ewdrag drag cursor-ew-resize" data-subplot="xy" x="101.6" y="220.5" width="172.8" height="20" style="fill: transparent; stroke-width: 0; pointer-events: all;"></rect><rect class="wdrag drag cursor-w-resize" data-subplot="xy" x="80" y="220.5" width="21.6" height="20" style="fill: transparent; stroke-width: 0; pointer-events: all;"></rect><rect class="edrag drag cursor-e-resize" data-subplot="xy" x="274.4" y="220.5" width="21.6" height="20" style="fill: transparent; stroke-width: 0; pointer-events: all;"></rect><rect class="nsdrag drag cursor-ns-resize" data-subplot="xy" x="59.5" y="112" width="20" height="96" style="fill: transparent; stroke-width: 0; pointer-events: all;"></rect><rect class="sdrag drag cursor-s-resize" data-subplot="xy" x="59.5" y="208" width="20" height="12" style="fill: transparent; stroke-width: 0; pointer-events: all;"></rect><rect class="ndrag drag cursor-n-resize" data-subplot="xy" x="59.5" y="100" width="20" height="12" style="fill: transparent; stroke-width: 0; pointer-events: all;"></rect></g></g><g class="layer-below"><g class="imagelayer"></g><g class="shapelayer"></g></g><g class="cartesianlayer"><g class="subplot xy"><g class="layer-subplot"><g class="shapelayer"></g><g class="imagelayer"></g></g><g class="gridlayer"><g class="x"><path class="xgrid crisp" d="M0,100v120" transform="translate(96.14,0)" style="stroke: rgb(238, 238, 238); stroke-opacity: 1; stroke-width: 1px;"></path><path class="xgrid crisp" d="M0,100v120" transform="translate(147.9,0)" style="stroke: rgb(238, 238, 238); stroke-opacity: 1; stroke-width: 1px;"></path><path class="xgrid crisp" d="M0,100v120" transform="translate(199.65,0)" style="stroke: rgb(238, 238, 238); stroke-opacity: 1; stroke-width: 1px;"></path><path class="xgrid crisp" d="M0,100v120" transform="translate(251.41,0)" style="stroke: rgb(238, 238, 238); stroke-opacity: 1; stroke-width: 1px;"></path></g><g class="y"><path class="ygrid crisp" d="M80,0h216" transform="translate(0,173.7)" style="stroke: rgb(238, 238, 238); stroke-opacity: 1; stroke-width: 1px;"></path><path class="ygrid crisp" d="M80,0h216" transform="translate(0,128.02)" style="stroke: rgb(238, 238, 238); stroke-opacity: 1; stroke-width: 1px;"></path></g></g><g class="zerolinelayer"></g><path class="xlines-below"></path><path class="ylines-below"></path><g class="overlines-below"></g><g class="xaxislayer-below"></g><g class="yaxislayer-below"></g><g class="overaxes-below"></g><g class="plot" transform="translate(80, 100)" clip-path="url(#clipe9bae5xyplot)"><g class="scatterlayer mlayer"><g class="trace scatter trace445ec3" style="stroke-miterlimit: 2; opacity: 1;"><path class="js-line" d="M14.55,9.75L31.83,23.45L46.18,28.02L80.69,32.59L97.94,37.16L115.19,28.02L149.69,18.89L184.2,14.32L201.45,28.02" style="vector-effect: non-scaling-stroke; fill: none; stroke: rgb(31, 119, 180); stroke-opacity: 1; stroke-width: 2px; opacity: 1;"></path><g class="points"><path class="point" transform="translate(14.55,9.75)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(31, 119, 180); fill-opacity: 1;"></path><path class="point" transform="translate(31.83,23.45)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(31, 119, 180); fill-opacity: 1;"></path><path class="point" transform="translate(46.18,28.02)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(31, 119, 180); fill-opacity: 1;"></path><path class="point" transform="translate(80.69,32.59)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(31, 119, 180); fill-opacity: 1;"></path><path class="point" transform="translate(97.94,37.16)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(31, 119, 180); fill-opacity: 1;"></path><path class="point" transform="translate(115.19,28.02)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(31, 119, 180); fill-opacity: 1;"></path><path class="point" transform="translate(149.69,18.89)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(31, 119, 180); fill-opacity: 1;"></path><path class="point" transform="translate(184.2,14.32)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(31, 119, 180); fill-opacity: 1;"></path><path class="point" transform="translate(201.45,28.02)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(31, 119, 180); fill-opacity: 1;"></path></g></g><g class="trace scatter trace265e2a" style="stroke-miterlimit: 2; opacity: 1;"><path class="js-line" d="M14.55,101.11L31.83,96.55L46.18,101.11L80.69,87.41L97.94,73.7L115.19,60L149.69,82.84L184.2,96.55L201.45,110.25" style="vector-effect: non-scaling-stroke; fill: none; stroke: rgb(255, 127, 14); stroke-opacity: 1; stroke-width: 2px; opacity: 1;"></path><g class="points"><path class="point" transform="translate(14.55,101.11)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(255, 127, 14); fill-opacity: 1;"></path><path class="point" transform="translate(31.83,96.55)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(255, 127, 14); fill-opacity: 1;"></path><path class="point" transform="translate(46.18,101.11)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(255, 127, 14); fill-opacity: 1;"></path><path class="point" transform="translate(80.69,87.41)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(255, 127, 14); fill-opacity: 1;"></path><path class="point" transform="translate(97.94,73.7)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(255, 127, 14); fill-opacity: 1;"></path><path class="point" transform="translate(115.19,60)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(255, 127, 14); fill-opacity: 1;"></path><path class="point" transform="translate(149.69,82.84)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(255, 127, 14); fill-opacity: 1;"></path><path class="point" transform="translate(184.2,96.55)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(255, 127, 14); fill-opacity: 1;"></path><path class="point" transform="translate(201.45,110.25)" d="M3,0A3,3 0 1,1 0,-3A3,3 0 0,1 3,0Z" style="opacity: 1; stroke-width: 0px; fill: rgb(255, 127, 14); fill-opacity: 1;"></path></g></g></g></g><g class="overplot"></g><path class="xlines-above crisp" d="M0,0" style="fill: none;"></path><path class="ylines-above crisp" d="M0,0" style="fill: none;"></path><g class="overlines-above"></g><g class="xaxislayer-above"><g class="xtick"><text text-anchor="start" x="0" y="233" data-unformatted="20:00<br>Dec 1, 2016" data-math="N" transform="translate(96.14,0) rotate(30,0,227)" style="font-family: "Open Sans", verdana, arial, sans-serif; font-size: 12px; fill: rgb(68, 68, 68); fill-opacity: 1; white-space: pre;"><tspan class="line" dy="0em" x="0" y="233">20:00</tspan><tspan class="line" dy="1.3em" x="0" y="233">Dec 1, 2016</tspan></text></g><g class="xtick"><text text-anchor="start" x="0" y="233" data-unformatted="20:30" data-math="N" transform="translate(147.9,0) rotate(30,0,227)" style="font-family: "Open Sans", verdana, arial, sans-serif; font-size: 12px; fill: rgb(68, 68, 68); fill-opacity: 1; white-space: pre;">20:30</text></g><g class="xtick"><text text-anchor="start" x="0" y="233" data-unformatted="21:00" data-math="N" transform="translate(199.65,0) rotate(30,0,227)" style="font-family: "Open Sans", verdana, arial, sans-serif; font-size: 12px; fill: rgb(68, 68, 68); fill-opacity: 1; white-space: pre;">21:00</text></g><g class="xtick"><text text-anchor="start" x="0" y="233" data-unformatted="21:30" data-math="N" transform="translate(251.41,0) rotate(30,0,227)" style="font-family: "Open Sans", verdana, arial, sans-serif; font-size: 12px; fill: rgb(68, 68, 68); fill-opacity: 1; white-space: pre;">21:30</text></g></g><g class="yaxislayer-above"><g class="ytick"><text text-anchor="end" x="79" y="4.2" data-unformatted="10" data-math="N" transform="translate(0,219.39)" style="font-family: "Open Sans", verdana, arial, sans-serif; font-size: 12px; fill: rgb(68, 68, 68); fill-opacity: 1; white-space: pre;">10</text></g><g class="ytick"><text text-anchor="end" x="79" y="4.2" data-unformatted="15" data-math="N" transform="translate(0,173.7)" style="font-family: "Open Sans", verdana, arial, sans-serif; font-size: 12px; fill: rgb(68, 68, 68); fill-opacity: 1; white-space: pre;">15</text></g><g class="ytick"><text text-anchor="end" x="79" y="4.2" data-unformatted="20" data-math="N" transform="translate(0,128.02)" style="font-family: "Open Sans", verdana, arial, sans-serif; font-size: 12px; fill: rgb(68, 68, 68); fill-opacity: 1; white-space: pre;">20</text></g></g></svg>
不幸的是,这个片段不会在这篇文章中运行 - 首先不能直接从github使用该脚本,但即使它可能,沙盒代码也不允许打开新窗口......我希望它可以帮助您在自己的环境中工作。