D3js 导出 SVG 到图像
D3js Export SVG to Image
我有这个 D3js line graph 我正在使用它。
我希望能够将其作为图像保存在与 this example
所示相同的目录中
d3.select('#saveButton').on('click', function(){
var svgString = getSVGString(svg.node());
svgString2Image( svgString, 2*width, 2*height, 'png', save ); // passes Blob and filesize String to the callback
function save( dataBlob, filesize ){
saveAs( dataBlob, 'D3 vis exported to PNG.png' ); // FileSaver.js
function
}
});
没有错误运行以上
虽然我没有收到任何错误,但单击按钮时文件并未下载。我在这里错过了什么?谢谢!
在您的 fiddle 中,您将 g
附加到 svg
并将其分配给您的变量 svg
:
var svg = d3.select("#priceWithMilestones")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
看起来 getSVGString()
需要根节点,而不是 g
元素。您可能应该更改您的代码,以便 svg
反映根 svg 元素,并创建另一个变量来存储 g
元素,但是为了快速而肮脏的修复,您可以更改
var svgString = getSVGString(svg.node());
至
var svgString = getSVGString(d3.select('svg').node());
并且应该保存。已更新 fiddle:https://jsfiddle.net/c19664p3/8/
编辑: 至于导出的样式,看起来您在声明选择时不能引用 svg 之外的选择器。此外,它看起来必须只包含一个 id 或一个 class。请参阅我的其他答案以获得更宽松的 CSS 规则导出器。
所以改变这个:
#priceWithMilestones .line {
fill: none;
stroke: #14da9e;
stroke-width: 2px;
}
至:
.line {
fill: none;
stroke: #14da9e;
stroke-width: 2px;
}
仅导出 svg 的线条样式。已更新 fiddle:https://jsfiddle.net/c19664p3/10/
在查看 getCSSStyles
之后,它似乎只检查匹配 完全匹配的规则 根 svg 的 id 或 class 及其子元素。我认为这是一个更宽容的实现:
function getCSSStyles( parentElement ) {
var nodesToCheck = [ parentElement ], i;
// Add all the different nodes to check
var childNodes = parentElement.getElementsByTagName("*");
for (i = 0; i < childNodes.length; i++) {
nodesToCheck.push(childNodes[i]);
}
// Extract CSS Rules
var extractedCSSRules = [];
for (i = 0; i < document.styleSheets.length; i++) {
var s = document.styleSheets[i];
try {
if (!s.cssRules) continue;
} catch( e ) {
if (e.name !== 'SecurityError') throw e; // for Firefox
continue;
}
var cssRules = s.cssRules;
var ruleMatches;
for (var r = 0; r < cssRules.length; r++) {
ruleMatches = nodesToCheck.reduce(function (a, b) {
return a || b.matches(cssRules[r].selectorText);
}, false);
if (ruleMatches)
extractedCSSRules.push(cssRules[r].cssText);
}
}
return extractedCSSRules.join(' ');
}
您仍然需要使用 svg 内部的规则(例如,您仍然需要在 CSS 中将 #priceWithMilestones .line
更改为 .line
),但对于未来的项目,我认为应该捕获更多元素。
已更新 fiddle,包含所有更改:https://jsfiddle.net/c19664p3/12/
我有这个 D3js line graph 我正在使用它。
我希望能够将其作为图像保存在与 this example
所示相同的目录中d3.select('#saveButton').on('click', function(){
var svgString = getSVGString(svg.node());
svgString2Image( svgString, 2*width, 2*height, 'png', save ); // passes Blob and filesize String to the callback
function save( dataBlob, filesize ){
saveAs( dataBlob, 'D3 vis exported to PNG.png' ); // FileSaver.js
function
}
});
没有错误运行以上
虽然我没有收到任何错误,但单击按钮时文件并未下载。我在这里错过了什么?谢谢!
在您的 fiddle 中,您将 g
附加到 svg
并将其分配给您的变量 svg
:
var svg = d3.select("#priceWithMilestones")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
看起来 getSVGString()
需要根节点,而不是 g
元素。您可能应该更改您的代码,以便 svg
反映根 svg 元素,并创建另一个变量来存储 g
元素,但是为了快速而肮脏的修复,您可以更改
var svgString = getSVGString(svg.node());
至
var svgString = getSVGString(d3.select('svg').node());
并且应该保存。已更新 fiddle:https://jsfiddle.net/c19664p3/8/
编辑: 至于导出的样式,看起来您在声明选择时不能引用 svg 之外的选择器。此外,它看起来必须只包含一个 id 或一个 class。请参阅我的其他答案以获得更宽松的 CSS 规则导出器。
所以改变这个:
#priceWithMilestones .line {
fill: none;
stroke: #14da9e;
stroke-width: 2px;
}
至:
.line {
fill: none;
stroke: #14da9e;
stroke-width: 2px;
}
仅导出 svg 的线条样式。已更新 fiddle:https://jsfiddle.net/c19664p3/10/
在查看 getCSSStyles
之后,它似乎只检查匹配 完全匹配的规则 根 svg 的 id 或 class 及其子元素。我认为这是一个更宽容的实现:
function getCSSStyles( parentElement ) {
var nodesToCheck = [ parentElement ], i;
// Add all the different nodes to check
var childNodes = parentElement.getElementsByTagName("*");
for (i = 0; i < childNodes.length; i++) {
nodesToCheck.push(childNodes[i]);
}
// Extract CSS Rules
var extractedCSSRules = [];
for (i = 0; i < document.styleSheets.length; i++) {
var s = document.styleSheets[i];
try {
if (!s.cssRules) continue;
} catch( e ) {
if (e.name !== 'SecurityError') throw e; // for Firefox
continue;
}
var cssRules = s.cssRules;
var ruleMatches;
for (var r = 0; r < cssRules.length; r++) {
ruleMatches = nodesToCheck.reduce(function (a, b) {
return a || b.matches(cssRules[r].selectorText);
}, false);
if (ruleMatches)
extractedCSSRules.push(cssRules[r].cssText);
}
}
return extractedCSSRules.join(' ');
}
您仍然需要使用 svg 内部的规则(例如,您仍然需要在 CSS 中将 #priceWithMilestones .line
更改为 .line
),但对于未来的项目,我认为应该捕获更多元素。
已更新 fiddle,包含所有更改:https://jsfiddle.net/c19664p3/12/