Javascript 使用D3.js(即safari和chrome)创建SVG后,如何保存/导出SVG文件?
我目前有一个使用D3的网站,我希望用户可以选择将SVG保存为SVG文件。我正在使用crowbar.js来实现这一点,但它只在chrome上起作用。safari没有发生任何事情,IE在crowbar.js中用于下载文件的Javascript 使用D3.js(即safari和chrome)创建SVG后,如何保存/导出SVG文件?,javascript,jquery,svg,d3.js,Javascript,Jquery,Svg,D3.js,我目前有一个使用D3的网站,我希望用户可以选择将SVG保存为SVG文件。我正在使用crowbar.js来实现这一点,但它只在chrome上起作用。safari没有发生任何事情,IE在crowbar.js中用于下载文件的click()方法上拒绝访问 var e = document.createElement('script'); if (window.location.protocol === 'https:') { e.setAttribute('src', 'https://r
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文件?共有5个步骤。我经常使用这种方法输出内联svg
//获取svg元素。
var svg=document.getElementById(“svg”);
//获取svg源代码。
var serializer=新的XMLSerializer();
var source=serializer.serializeToString(svg);
//添加名称空间。
如果(!source.match(/^]+xmlns=“http\:\/\/www\.w3\.org\/2000\/svg/){
source=source.replace(/^我知道这个问题已经得到了回答,而且这个答案在大多数情况下都很有效。但是我发现如果svg图像太大(大约1MB),它在Chrome(但不是Firefox)上失败了。如果您返回到使用Blob
构造,它会起作用,如所述和所述。唯一的区别是类型参数。在我的代码中,我希望只需按下一个按钮即可为用户下载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上运行。结合了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);
}
要使此代码段正常工作,您需要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");
};
函数将_另存为_svg(){
var svg_data=document.getElementById(“svg”).innerHTML//将svg元素的id放在此处
变量头=“”
//若你们有一些额外的样式,比如图边,把它们放在标签里面
var style='圆圈{光标:指针;笔划宽度:1.5px;}文本{字体:10px arial;}路径{笔划:DimGrey;笔划宽度:1.5px;}'
var full_svg=头部+样式+svg_数据+“”
var blob=new blob([full_svg],{type:“image/svg+xml”});
saveAs(blob,graph.svg);
};
我尝试了这里的所有解决方案,但没有任何效果。我的图片总是比我的d3.js画布小
我必须设置画布的宽度
,高度
,然后在上下文
上执行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;
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);
它用于保存文件
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);
这是我的画布创建,请注意,我在这里解决了名称空间问题
d3.js画布创建:
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;
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);
在回答这个问题的同时,我创建了一个名为的小库,它可以帮助保存D3.js生成的SVG,该SVG使用外部样式表或外部定义文件(使用
和def
)标记。基于@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>
函数save_as_svg(){
fetch('path/./assets/chart.css')
.then(response=>response.text())
。然后(文本=>{
var svg_data=document.getElementById(“svg”).innerHTML
变量头=“”
var style=”“+文本+“”
var full_svg=头部+样式+svg_数据+“”
var blob=new blob([full_svg],{type:“image/svg+xml”});
saveAs(blob,graph.svg);
})
};
将_另存为_svg();
上面的代码读取您的chart.css,然后将css代码嵌入到您的svg文件中。谢谢您的回答!这为我下载了一个svg,尽管所有内容都变黑了,颜色也非常鲜艳。为什么会这样?您可以在我的网站上看到我的意思,我已经应用了您建议的代码:-只需单击“提交”,然后单击“导出图形”。非常感谢此示例非常简单。如果您通过链接元素使用外部css文件的css样式,则svg和样式表的链接已断开。因此,此问题将通过向内联svg添加样式数据来解决。“因此,此问题将通过向内联svg添加样式数据来解决。”你能用另一种方式向我解释一下吗?我不太明白。看吧,添加和转换,但在这种情况下svg文件将不再是独立的。注意:这在Chrome或Firefox中不再起作用,因为它们现在在顶层使用时都会阻止svg的数据URI。这在Chrome中非常有效!对于这个简单的答案,我会给出+100!看起来像它不需要在文档中追加和删除下载链接
。body
。outerHTML
在internet explorer中不起作用。但是您可以使用XMLSerializer()
作为。其他一切都保持不变。XMLSerializer()的良好替代品!这是最有效的!回答很好,代码段也很容易使用。svgEl.outerHTML
在IE和Edge中不起作用。他们不支持SVG元素的outerHTML
。我想将SVG静默保存在服务器上的文件夹中,我不想触发用户下载。如何完成请帮助我。谢谢!@senz,如果SVG包含ima呢由于某种原因,这不起作用。请检查我的示例。