我目前有一个使用 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://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 元素。通过 XMLSerializer 获取 svg 源。添加 svg 和 xlink 的命名空间。通过 encodeURIComponent 方法构造 svg 的 url 数据方案。将此 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.
我知道这已经得到了回答,而且这个答案在大多数情况下都很有效。但是,如果 svg 图像很大(大约 1MB),我发现它在 Chrome(但不是 Firefox)上失败。如果您重新使用 Blob
构造,它会起作用,如 here 和 here 所述。唯一的区别是类型参数。在我的代码中,我想要一个按钮来为用户下载 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 上运行。
document.body
中附加和删除 downloadLink
即可工作
结合戴夫和 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')
要使此代码段正常工作,您需要 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");
};
我在这里尝试了所有解决方案,但对我没有任何帮助。我的图片总是比我的 d3.js 画布小。
我必须设置画布 width
、height
,然后在 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);
基于@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文件中。
在我的场景中,我不得不在其他项目中使用一些使用 D3.js 创建的 svg 图像。所以我打开了开发工具并检查了那些 svg 并复制了它们的内容。然后创建一个新的空白 svg 文件并将复制的内容粘贴到那里。然后我在其他领域使用了那些新的 svg 文件。
如果你想以编程方式进行,那么我们可以使用 document.getElementById('svgId')
我知道这是一种基本方法,但万一有人觉得它有用。
我试试这个并为我工作。
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);
}