使用D3.js(IE、Safari和Chrome)创建SVG后,如何保存/导出SVG文件?

toe95027  于 2022-11-12  发布在  其他
关注(0)|答案(9)|浏览(816)

我目前有一个使用D3的网站,我希望用户可以选择将SVG保存为SVG文件。我使用crowbar.js来做这件事,但它只能在chrome上工作。safari没有任何React,IE拒绝访问crowbar.js中使用的click()方法来下载文件。

var e = document.createElement('script'); 

if (window.location.protocol === 'https:') { 
    e.setAttribute('src', 'https://raw.github.com/NYTimes/svg-crowbar/gh-pages/svg-crowbar.js'); 
} else { 
    e.setAttribute('src', 'http://nytimes.github.com/svg-crowbar/svg-crowbar.js'); 
}

e.setAttribute('class', 'svg-crowbar'); 
document.body.appendChild(e);

如何在Safari、IE和chrome中下载基于我网站上SVG元素的SVG文件?

xcitsw88

xcitsw881#

有5个步骤,我经常用这个方法输出内联svg。
1.获取要输出内联SVG元素。
1.通过XMLSerializer获取SVG源。
1.添加svg和xlink的命名空间。
1.利用encodeURIComponent方法构造svgurl数据模式。
1.将此url设置为某个“a”元素href属性,然后右键单击此链接以下载SVG文件。

//get svg element.
var svg = document.getElementById("svg");

//get svg source.
var serializer = new XMLSerializer();
var source = serializer.serializeToString(svg);

//add name spaces.
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"');
}

//add xml declaration
source = '<?xml version="1.0" standalone="no"?>\r\n' + source;

//convert svg source to URI data scheme.
var url = "data:image/svg+xml;charset=utf-8,"+encodeURIComponent(source);

//set url value to a element's href attribute.
document.getElementById("link").href = url;
//you can download svg file by right click menu.
vzgqcmou

vzgqcmou2#

我知道这个问题已经得到了解答,而且这个答案大部分时间都很好用。但是我发现它在Chrome上失败了(但不是Firefox)如果svg图像比较大如果您返回使用Blob结构,如herehere所述。唯一的区别是类型参数。在我的代码中,我希望通过单击一个按钮为用户下载svg,我使用以下代码实现了这一点:

var svgData = $("#figureSvg")[0].outerHTML;
var svgBlob = new Blob([svgData], {type:"image/svg+xml;charset=utf-8"});
var svgUrl = URL.createObjectURL(svgBlob);
var downloadLink = document.createElement("a");
downloadLink.href = svgUrl;
downloadLink.download = "newesttree.svg";
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);

**2019年10月编辑:**评论指出,即使没有将downloadLink附加到document.body,然后在click()之后删除它,这段代码也可以工作。我相信这段代码曾经在Firefox上工作过,但现在不再工作了(Firefox要求你附加downloadLink,然后删除它)。这段代码在Chrome上都可以工作。

7gcisfzg

7gcisfzg3#

结合Dave和defghi1977的答案。下面是一个可重用函数:

function saveSvg(svgEl, name) {
    svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
    var svgData = svgEl.outerHTML;
    var preface = '<?xml version="1.0" standalone="no"?>\r\n';
    var svgBlob = new Blob([preface, svgData], {type:"image/svg+xml;charset=utf-8"});
    var svgUrl = URL.createObjectURL(svgBlob);
    var downloadLink = document.createElement("a");
    downloadLink.href = svgUrl;
    downloadLink.download = name;
    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
}

调用示例:

saveSvg(svg, 'test.svg')
6l7fqoea

6l7fqoea4#

要使此代码段正常工作,您需要FileSaver.js。

function save_as_svg(){

        var svg_data = document.getElementById("svg").innerHTML //put id of your svg element here

        var head = '<svg title="graph" version="1.1" xmlns="http://www.w3.org/2000/svg">'

        //if you have some additional styling like graph edges put them inside <style> tag

        var style = '<style>circle {cursor: pointer;stroke-width: 1.5px;}text {font: 10px arial;}path {stroke: DimGrey;stroke-width: 1.5px;}</style>'

        var full_svg = head +  style + svg_data + "</svg>"
        var blob = new Blob([full_svg], {type: "image/svg+xml"});  
        saveAs(blob, "graph.svg");

};
sulc1iza

sulc1iza5#

我尝试了这里的所有解决方案,但没有一个对我有效。我的图片总是比我的d3.js画布小。

我必须设置画布widthheight,然后在context上做一个clearRect才能让它工作。

导出功能:

var svgHtml = document.getElementById("d3-canvas"),
    svgData = new XMLSerializer().serializeToString(svgHtml),
    svgBlob = new Blob([svgData], {type:"image/svg+xml;charset=utf-8"}),
    bounding = svgHtml.getBoundingClientRect(),
    width = bounding.width * 2,
    height = bounding.height * 2,
    canvas = document.createElement("canvas"),
    context = canvas.getContext("2d"),
    exportFileName = 'd3-graph-image.png';

//Set the canvas width and height before loading the new Image
canvas.width = width;
canvas.height = height;

var image = new Image();
image.onload = function() {
    //Clear the context
    context.clearRect(0, 0, width, height);
    context.drawImage(image, 0, 0, width, height);

    //Create blob and save if with FileSaver.js
    canvas.toBlob(function(blob) {
        saveAs(blob, exportFileName);
    });     
};
var svgUrl = URL.createObjectURL(svgBlob);
image.src = svgUrl;

它使用FileSaver.js来保存文件。
这是我的画布创建,注意我在这里解决了命名空间问题。

d3.js画布创建:

var canvas = d3.select("body")
    .insert("svg")
    .attr('id', 'd3-canvas')
    //Solve the namespace issue (xmlns and xlink)
    .attr("xmlns", "http://www.w3.org/2000/svg")
    .attr("xmlns:xlink", "http://www.w3.org/1999/xlink")
    .attr("width", width)
    .attr("height", height);
jmo0nnb3

jmo0nnb36#

虽然这个问题已经得到了解答,但我创建了一个名为SaveSVG的小型库,它可以帮助保存D3.js生成的SVG,这些SVG使用外部样式表或外部定义文件(使用<use>def)标记。

ha5z0ras

ha5z0ras7#

根据@vasyl-vaskivskyi的回答。

<script src="../../assets/FileSaver.js"></script>
<script>
function save_as_svg(){
    fetch('path/../assets/chart.css')
    .then(response => response.text())
    .then(text => {
        var svg_data = document.getElementById("svg").innerHTML
        var head = '<svg title="graph" version="1.1" xmlns="http://www.w3.org/2000/svg">'
        var style = "<style>" + text + "</style>"
        var full_svg = head +  style + svg_data + "</svg>"
        var blob = new Blob([full_svg], {type: "image/svg+xml"});  
        saveAs(blob, "graph.svg");
    })
};
save_as_svg();
</script>

上面的代码读取chart.css,然后将css代码嵌入svg文件。

1bqhqjot

1bqhqjot8#

在我的场景中,我不得不在其他项目中使用一些用D3.js创建的svg图像。所以我打开dev工具,检查那些svg并复制它们的内容。然后创建一个新的空白svg文件,并将复制的内容粘贴到那里。然后我在其他区域使用这些新的svg文件。
如果你想以编程的方式完成它,那么我们可以使用document.getElementById('svgId ')
我知道这是一个基本的方法,但如果有人发现它有用。

dy1byipe

dy1byipe9#

我试过了,效果很好

function downloadSvg() {

var svg = document.getElementById("svg");
var serializer = new XMLSerializer();
var source = serializer.serializeToString(svg);
source = source.replace(/(\w+)?:?xlink=/g, 'xmlns:xlink='); // Fix root xlink without namespace

source = source.replace(/ns\d+:href/g, 'xlink:href'); // Safari NS namespace fix.

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

var preface = '<?xml version="1.0" standalone="no"?>\r\n';
var svgBlob = new Blob([preface, source], { type: "image/svg+xml;charset=utf-8" });
var svgUrl = URL.createObjectURL(svgBlob);
var downloadLink = document.createElement("a");
downloadLink.href = svgUrl;
downloadLink.download = name;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);

}

相关问题